使用 FlatList 中项目的 index/key 响应 Native TouchableOpacity onPress

React Native TouchableOpacity onPress using index/key of the item in FlatList

我们在我们的应用程序中创建了一个 FlatList 组件和一个联系人屏幕。我们想在联系人屏幕中的图像附近添加 'heart' 图标。我们在所有项目附近添加了心形图标。但是,如果我们按下其中一个图标,它会将所有图标的颜色更改为红色,而不仅仅是其中一个。我们想改变点击项目的颜色。

我们的程序截图:

这是我们的 FlatList 组件:

import React, { Component } from 'react';
import { View, Text, SafeAreaView, StyleSheet, FlatList, Image, TouchableOpacity, 
TouchableWithoutFeedback, TextInput } from 'react-native';
import { Right, Icon } from 'native-base';
import data from '../../data';

export default class FlatListComponent extends Component {
  state = {
    text: '',
    contacts: data,
    like: false,
    color: 'white',
  }

  toggleLike=()=>{
    this.setState({
        like: !this.state.like
    })

    if(this.state.like){
      this.setState({
        color: 'red',
    })
    }else{
      this.setState({
      color: 'white',
   })
 }
 }

renderContactsItem = ({item, index}) => {

return (
  <View style={[styles.itemContainer]}>
    <Image
      style={styles.avatar}
      source={{ uri: item.image }} />
    <View style={styles.textContainer}>
      <Text style={[styles.name], {color: '#fafafa'}}>{item.first_name}</Text>
      <Text style={{ color: '#fafafa' }}>{item.last_name}</Text>
    </View>
    <Right style={{justifyContent: 'center'}}>
      <TouchableWithoutFeedback onPress={this.toggleLike}>
        {/*{this.like ? (
            <Icon name="heart" type='FontAwesome' style={{paddingRight: 10, fontSize: 30, color: 'red'}} />
          ) : 
          ( <Icon name="heart" type='FontAwesome' style={{paddingRight: 10, fontSize: 30, color: 'white'}} /> )
        }*/}
        <Icon name='heart' type='FontAwesome' size={32} style={{color: this.state.color === "white" ? 'white' :'red', paddingRight: 10 }}/>
        {/*<Icon name="heart" type='FontAwesome' style={{paddingRight: 10, fontSize: 30, color: this.state.color}} />*/}
      </TouchableWithoutFeedback>
    </Right>
  </View>
);
}

searchFilter = text => {
  const newData = data.filter(item => {
    const listItems = `${item.first_name.toLowerCase()}`
    return listItems.indexOf(text.toLowerCase()) > -1;
  });

  this.setState({
    contacts: newData,
  });
};

renderHeader = () => {
  const {text} = this.state;
  return (
    <View style={styles.searchContainer}>
      <TextInput 
        onChangeText = {text => {
          this.setState ({
            text,
          });
          this.searchFilter(text);
        }}
        value={text}
        placeholder="Search..." 
        style={styles.searchInput} />
    </View>
  )
}

render() {
  return (
    <FlatList
      ListHeaderComponent={this.renderHeader()}
      renderItem={this.renderContactsItem}
      keyExtractor={item => item.id}
      data={this.state.contacts}
    />
  );
}
}

 const styles = StyleSheet.create({
itemContainer: {
  flex: 1,
  flexDirection: 'row',
  paddingVertical: 10,
  borderBottomWidth: 1,
  borderBottomColor: '#eee'
},
avatar: {
  width: 50,
  height: 50,
  borderRadius: 25,
  marginHorizontal: 10,
},
textContainer: {
  justifyContent: 'space-around',
},
name: {
  fontSize: 16,
},
searchContainer: {
  padding: 10

},
searchInput: {
  fontSize: 16,
  backgroundColor: '#f9f9f9',
  padding: 10,
}
});

我们的联系人屏幕是:

import React from 'react';
import 'SafeAreaView' from 'react-native';
import FlatList from './FlatList';

export default function Contact() {
    <SafeAreaView style={{ flex: 1 }}>
        <FlatList />
    </SafeAreaView>
}

我们如何实施?

我最近 运行 对此 :) 一种选择是使 renderContactsItem 成为它自己的组件。例如:

const RenderContactsItem = ({item, index}) => {

 const [like, setLike] = useState(false);
 const [color, setColor] = useState("white");

 const toggleLike = () => {
  setLike(!like)
  if(like) {
   setColor("red");
  } else {
   setColor("white");
  }
 }

 return (
  <View style={[styles.itemContainer]}>
    <Image
      style={styles.avatar}
      source={{ uri: item.image }} />
    <View style={styles.textContainer}>
      <Text style={[styles.name], {color: '#fafafa'}}>{item.first_name}</Text>
      <Text style={{ color: '#fafafa' }}>{item.last_name}</Text>
    </View>
    <Right style={{justifyContent: 'center'}}>
      <TouchableWithoutFeedback onPress={toggleLike}>
        <Icon name='heart' type='FontAwesome' size={32} style={{color, paddingRight: 10 }}/>
      </TouchableWithoutFeedback>


    </Right>
   </View>
  );
}

在这种情况下,每个项目管理自己的状态,因此设置 like 不会为 每个 项目设置它。

另一种选择是构建一个具有“类似”状态的对象,并在按下红心时设置值。例如:

state = {
 text: '',
 contacts: data,
 like: {},
 color: 'white', // You don't need this
}

然后,当一颗心被按下时,你可以发送toggleLike index,然后像这样设置状态:

toggleLike = (index) => {
  let newLike = {...this.state.like};
  newLike[index] = !Boolean(newLike[index]);
  this.setState({
   like: newLike,
  });
}

并根据 like 状态的索引值有条件地渲染颜色,如下所示:

<Icon name='heart' type='FontAwesome' size={32} style={{color: this.state.like[index] ? 'red' :'white', paddingRight: 10 }}/>