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

如何正确更新React中的嵌套State以切换按钮选中状态?

嵌套React State的正确更新方式

你的代码存在几个核心问题,导致状态无法正确更新、子组件无法同步刷新,以下是问题分析和正确实现方案:

错误点分析

  • 直接修改State对象的属性(pref.selected = ...):React依赖State的引用变化触发重渲染,直接修改原对象不会生成新引用,React无法感知状态变更。
  • 硬编码id判断:只处理了intro中的两个id,完全没覆盖experience的元素,逻辑扩展性极差。
  • 传递原对象给setButtonObject:没有创建新的对象/数组副本,React会认为State没有变化,跳过重渲染。

正确实现代码

const handleButtonClick = ({ id }) => {
  setButtonObject(prevState => {
    // 遍历state中的所有分组(intro、experience)
    return Object.fromEntries(
      Object.entries(prevState).map(([groupKey, groupItems]) => {
        // 对当前分组的数组进行不可变更新
        const updatedItems = groupItems.map(item => {
          // 找到目标id的元素,切换selected状态
          if (item.id === id) {
            return { ...item, selected: !item.selected };
          }
          // 其他元素直接返回原对象
          return item;
        });
        return [groupKey, updatedItems];
      })
    );
  });
};

关键要点

  • 使用函数式更新:通过prevState获取最新的State值,避免闭包导致的旧值问题。
  • 不可变更新:
    • 对每个分组数组使用map生成新数组,不修改原数组。
    • 对需要修改的元素,用扩展运算符{ ...item }创建新对象,仅修改selected属性,保留其他属性不变。
    • 用Object.entries和Object.fromEntries处理顶层分组对象,生成新的顶层对象,确保引用变化。
  • 通用逻辑:无需硬编码id或分组名称,自动处理所有分组中的元素,扩展性强。

简化版(针对固定分组)

如果你的分组固定只有intro和experience,可以写更直观的版本:

const handleButtonClick = ({ id }) => {
  setButtonObject(prevState => ({
    ...prevState,
    intro: prevState.intro.map(item => 
      item.id === id ? { ...item, selected: !item.selected } : item
    ),
    experience: prevState.experience.map(item => 
      item.id === id ? { ...item, selected: !item.selected } : item
    )
  }));
};

内容的提问来源于stack exchange,提问作者Taylor Dorsett

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 09:18:25