React Native:如何为每个列表项设置独立状态
问题分析与解决方案
嘿,我一眼就看出问题所在啦——你现在整个DiscoveryComponent只用了一个starSelected状态来控制所有卡片的星星图标,所有卡片都绑定同一个状态值,那点击任何一个星星,所有自然都会跟着变咯!
要解决这个问题,我们得让每个卡片拥有独立的选中状态,而不是共用一个全局的状态。下面是具体的修改方案:
第一步:调整状态结构
把原来单个布尔值的starSelected改成一个对象,用来存储每个discovery的选中状态(如果你的discovery有唯一id最好用id当键,没有的话用索引也可以):
export default class DiscoveryComponent extends Component { constructor(props) { super(props) // 初始化空对象,每个键对应一个discovery的选中状态 this.state = { starSelected: {} }; } static propTypes = { discoveries: PropTypes.array.isRequired };
第二步:修改点击事件方法
让onPressStar接收一个标识(比如discovery的id或者当前索引),只切换对应项的状态:
onPressStar(discoveryId) { this.setState(prevState => ({ starSelected: { ...prevState.starSelected, // 翻转对应discovery的选中状态,没设置过默认是false [discoveryId]: !prevState.starSelected[discoveryId] } })) }
第三步:渲染时匹配对应状态
遍历卡片的时候,根据当前discovery的标识(这里假设你的discovery有id字段,如果没有就用index)来获取对应的选中状态:
render() { return ( this.props.discoveries.map((discovery, index) => { // 用id或者index当标识,优先用唯一id更可靠 const identifier = discovery.id || index; const isSelected = this.state.starSelected[identifier] || false; return ( <Card key={identifier} style={{flex: 0}}> <CardItem> <TouchableOpacity style={[styles.star]} onPress={() => this.onPressStar(identifier)}> <Icon style={[styles.iconStar]} name={isSelected ? 'star' : 'star-outline'} /> </TouchableOpacity> </CardItem> </Card> ) }) ); } }
额外小提醒
如果你的discoveries数据是从后端获取的,优先用每个discovery自带的唯一id做标识,比用索引更稳妥——毕竟数据顺序变化时,索引对应的项会改变,但id始终关联同一个条目。另外把onPress绑定在TouchableOpacity上,用户点击星星周围区域也能触发事件,交互体验会更好。
内容的提问来源于stack exchange,提问作者dylanolv
相关产品推荐
相关产品推荐

