You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

可选优化方案

  1. 用FlatList替代ScrollView手动遍历渲染,列表项数量较多时性能更优,原生支持滑动优化、懒加载、头部/尾部渲染等能力
  2. 不修改原始食材数据的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 07:06:06