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

React中变量自增操作每次加2而非加1的问题求助

问题分析与解决方案

核心问题

你遇到的数值每次加2的情况,主要由两个原因导致:

  1. 状态突变:代码中对prevChar仅做了浅拷贝,newChar.primary_class和newChar.multiclass仍引用原状态对象,直接修改这些对象的属性属于React禁止的状态突变行为。
  2. StrictMode重复执行:React开发环境的StrictMode模式下,会重复调用状态更新的函数式回调(比如setLeveledChar的回调)来检测不纯副作用。由于你的回调存在状态突变,重复执行就会让自增逻辑跑两次,最终数值加2。

而setCounter(counter + 1)只加1,是因为它基于当前counter值更新,同一批次更新中counter不会变化,即使执行两次,最终结果还是counter + 1。

修复代码

1. 彻底解决状态突变问题

对嵌套对象进行完整拷贝,确保所有修改都基于新对象,遵循React不可变状态原则:

const [counter, setCounter] = useState(0)

const handleSubmit = () => {
  // 改用函数式更新,避免并发更新问题
  setCounter(prev => prev + 1)

  console.log('handleSubmit is running', counter)

  setLeveledChar(prevChar => {
    // 深拷贝主职业对象
    const newPrimaryClass = { ...prevChar.primary_class };
    // 深拷贝多职业数组中的每个对象
    const newMulticlass = prevChar.multiclass.map(cls => ({ ...cls }));

    // 构建全新的newChar,所有嵌套对象都是新引用
    let newChar = {
      ...prevChar,
      primary_class: newPrimaryClass,
      multiclass: newMulticlass,
      // 用赋值代替++,避免直接突变属性
      char_level: prevChar.char_level + 1
    };

    const leveledClass = isMulticlassing
      ? newChar.multiclass.find(x => x.name === selectedClass.name)
      : newChar.primary_class
        
    if (leveledClass) {
      // 同样用赋值方式自增,确保操作的是新对象
      leveledClass.level = leveledClass.level + 1;
    }

    return newChar
  })
}

2. 开发环境临时验证(可选)

如果只是想快速验证,可以暂时移除项目入口文件(比如index.js)中的<React.StrictMode>包裹,这样状态更新回调不会被重复执行。但这只是临时方案,修复状态突变才是根本解决办法。

内容的提问来源于stack exchange,提问作者Christopher Dirksen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:12:38