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

React点击时toggle功能失效,控制台输出重复值问题排查

React数组对象Toggle失效、控制台重复输出数值的问题排查与解决

问题原因

  1. 违反状态不可变性原则:你用[...oldArr]复制数组,但数组内的对象是引用类型,newArr[0]和原数组的第一个对象指向同一块内存空间,直接修改newArr[0].componentId本质是在修改原状态对象,这不符合React的状态更新规范。
  2. React严格模式的影响:在开发环境下,React严格模式会两次执行状态更新回调函数来检测副作用。第一次执行时把componentId改成1,第二次执行时因为引用没断,还是基于原对象(值为0)再次修改,又改回0,最终状态没有变化,控制台就会输出1和0。

修复方案

遵循React状态不可变性要求,修改数组中的对象时,必须创建新的对象实例,而不是直接修改原对象。可以用map方法遍历数组,对目标元素生成新对象:

const { useState } = React;

const App = () => {
  const [Btns, setBtns] = useState([
    { componentId: 0 },
    { componentId: 0 }
  ]);

  return (
    <div>
      <button
        onClick={() => {
          setBtns(oldArr => 
            oldArr.map((item, idx) => 
              idx === 0 
                ? { ...item, componentId: item.componentId === 0 ? 1 : 0 } 
                : item
            )
          );
        }}
      >
        Button
      </button>
      {/* 新增展示,直观验证toggle效果 */}
      <p>第一个按钮的componentId:{Btns[0].componentId}</p>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("react"));

修复说明

  • 用map遍历数组,对需要修改的元素(索引0),通过扩展运算符{...item}创建新对象,再覆盖componentId值,完全脱离对原状态对象的引用。
  • 即使严格模式下两次执行更新函数,每次都是基于上一次的正确状态计算新值,最终状态会正常切换,控制台也不会出现重复的回滚输出。

内容的提问来源于stack exchange,提问作者s.kuznetsov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:03:38