React Native中TouchableOpacity的onPress需点击两次才切换样式问题求助
问题修复方案
核心问题原因
- 列表渲染时遍历的是初始常量
itemsData,而非状态变量items,状态更新后视图没有对应刷新 - 更新状态时直接修改原数组内对象的属性,没有遵循React状态不可变原则,React无法正常识别状态变更触发重渲染
- 调用
AddToPanetry时使用了更新前的旧状态,setItems是异步方法,执行后当前作用域的items不会立刻更新
修正后代码
const Test = ({ navigation }) => { const itemsData = GetGroceryIngridients(); const [items, setItems] = useState(itemsData); const handleSelectItem = (selectedItemIndex) => { // 遵循不可变原则,返回新数组+新对象,不修改原状态引用 const itemsToSelect = items.map((item, index) => { if (selectedItemIndex === index) { return {...item, pressed: !item.pressed}; } return item; }); setItems(itemsToSelect); // 取更新后的数组项传值 AddToPanetry(itemsToSelect[selectedItemIndex].label); }; const renderItem = (item, index) => { const isSelected = items[index].pressed; return ( <TouchableOpacity style={[styles.button, isSelected && styles.selectedButton]} onPress={() => handleSelectItem(index)} activeOpacity={0.7} // 可选:添加点击反馈透明度,提升交互感知 > <Image style={{ height: 110, width: 100, borderRadius: 50 }} source={item.image} /> {/* 修复:原数据字段是label不是name,避免显示空文本 */} <Text>{item.label}</Text> </TouchableOpacity> ); }; return ( <View> <ScrollView> <TouchableOpacity onPress={() => navigation.navigate("IngridientsScreen")} > <Ionicons style={{ width: 50, height: 50 }} name="arrow-back-circle-sharp" size={50} color="#eb344f" /> </TouchableOpacity> {/* 修复:遍历状态变量items而非初始常量itemsData */} {items.map((item, index) => renderItem(item, index))} </ScrollView> </View> ); }; const styles = StyleSheet.create({ button: { opacity: 1, padding: 20, }, selectedButton: { opacity: 0.5, }, }); export default Test;
可选优化方案
- 用
FlatList替代ScrollView手动遍历渲染,列表项数量较多时性能更优,原生支持滑动优化、懒加载、头部/尾部渲染等能力 - 不修改原始食材数据的
pressed属性,单独用状态存储选中的索引集合,逻辑更解耦:
// 初始化选中集合 const [selectedSet, setSelectedSet] = useState(new Set( itemsData.filter(item => item.pressed).map((_, idx) => idx) )) // 判断选中逻辑 const isSelected = selectedSet.has(index) // 切换选中逻辑 const handleSelect = (idx) => { const newSet = new Set(selectedSet) newSet.has(idx) ? newSet.delete(idx) : newSet.add(idx) setSelectedSet(newSet) }
内容的提问来源于stack exchange,提问作者DavidB
相关产品推荐
相关产品推荐

