React Native中map循环内如何仅修改被按下列表行的样式与属性
问题原因
你现在所有列表行共用同一个样式状态,只要状态更新,所有绑定了这个状态的行都会同步改样式,根本做不到单行单独变化。
正确实现思路
别存整段激活样式,只存当前被选中行的唯一标识就行——优先用列表项自带的业务id,没有的话临时用map返回的index也可以。渲染每一行的时候,判断当前行的标识和存的激活标识是不是一致,一致就叠加激活样式,不一致就用默认样式。
直接替换成下面的代码就能用:
// 仅存储当前激活行的索引,初始值为null表示默认无激活项 const [activeIndex, setActiveIndex] = useState<number | null>(null); const handlerOnPress = (index: number) => { // 如果需要点击同一行第二次取消激活,就用下面这行判断,不需要的话直接setActiveIndex(index)就行 setActiveIndex(prev => prev === index ? null : index); } return data.map( (item, index) => { // 动态拼接当前行样式 const currentRowStyle = activeIndex === index ? [ styles.container, { backgroundColor: AppColors.tertiary, padding: 10, borderRadius: 10, } ] : styles.container; return ( <TouchableOpacity key={index} activeOpacity={0.3} onPress={() => handlerOnPress(index)} > <View style={currentRowStyle}> <Text style={{ ...globalStyle.subTitle, color: AppColors.black }}>{item}</Text> </View> </TouchableOpacity> ) });
优化提示
- 如果你的列表会动态增删、调整排序,不要用index当激活判断依据和key值,换成每个item自带的唯一id(比如
item.id),不然列表重排后会出现激活行错位的问题 - React Native支持用数组传样式,数组里靠后的样式会覆盖前面的同名属性,不用手动写对象合并
- 要是想要手指按下去还没抬起就立刻显示激活效果,把触发状态更新的逻辑从
onPress挪到onPressIn,需要抬手就恢复的话在onPressOut里重置状态即可
内容的提问来源于stack exchange,提问作者Jun De Leon
相关产品推荐
相关产品推荐

