React Native动态数据下点击按钮批量变色而非单个的问题
点击单个按钮导致所有按钮变色的问题修复
问题根源
你在父组件的onChange函数里,给isSelected赋值的是字符串类型的'true'和'false',但子组件中selected属性期望的是布尔类型的值。在JavaScript里,任何非空字符串都会被判定为true,所以不管数据里的isSelected是'true'还是'false',子组件的条件判断selected ? 'red' : 'blue'都会走true分支,所有按钮都显示红色。
另外代码还有两个可优化的点:
- 没必要通过
ref获取选中的title,子组件点击时已经把title作为参数传给了onChange,直接用这个参数就行 - 父组件中
map回调的index参数和外层onChange的index重名,会导致变量覆盖,虽然当前不影响功能,但容易引发其他问题
修复后的代码
父组件修改
const Usage = () => { const [data, setData] = useState(UsageDataMock1); // 如果不需要ref可以直接删掉下面这行 const invoiceTitleRef = []; const onChange = (_, selectedTitle) => { // 直接用子组件传过来的selectedTitle,不用ref setData(data.map(item => { // 赋值布尔类型的true/false,不是字符串 return { ...item, isSelected: item.title === selectedTitle }; })); }; return ( <AppBackground> <View style={{flexDirection: 'row', marginTop: 50}}> {data.map((item, index) => ( <InvoiceTitle key={item.id} title={item.title} selected={item?.isSelected ?? false} // 兜底默认布尔值 onChange={onChange} index={index} /> ))} </View> </AppBackground> ); }; const styles = StyleSheet.create({ container : { flexDirection : 'row', marginTop : 40, }, titleContainer : { marginHorizontal : 10, alignSelf : 'flex-start', paddingHorizontal : 10, paddingVertical : 8, borderRadius : 12, } }); export default Usage;
子组件修改(移除无用ref,简化逻辑)
const InvoiceTitle = ({ title, onChange, index, selected = false, ...props }: InvoiceTitleProps) => { // 不需要ref的话直接删掉下面这部分,如果确实需要ref再保留 // useImperativeHandle(ref, () => ({ // getSelectedTitle : () => title // })) const onClick = () => { onChange(index, title); }; return ( <Pressable onPress={onClick} style={({pressed}) => [ styles.titleContainer, { backgroundColor: selected ? 'red' : 'blue', opacity: pressed ? 0.5 : 1 } ]}> <AppText>{title}</AppText> </Pressable> ); }; const styles = StyleSheet.create({ container : { flexDirection : 'row', marginTop : 40, }, titleContainer : { marginHorizontal : 10, alignSelf : 'flex-start', paddingHorizontal : 10, paddingVertical : 8, borderRadius : 12, } }); export default InvoiceTitle; interface InvoiceTitleProps { title : string; onChange : (index: number, title: string) => void; index : number; selected? : boolean; // 设为可选,配合默认值 }
关键修复点总结
- 把
isSelected的赋值从字符串'true'/'false'改成布尔值true/false - 移除不必要的
ref引用,直接用子组件传递的title参数 - 给
selected属性设置兜底的布尔默认值,避免初始状态下undefined引发的判断问题
内容的提问来源于stack exchange,提问作者Anil Saxena
相关产品推荐
相关产品推荐

