React中变量自增操作每次加2而非加1的问题求助
问题分析与解决方案
核心问题
你遇到的数值每次加2的情况,主要由两个原因导致:
- 状态突变:代码中对
prevChar仅做了浅拷贝,newChar.primary_class和newChar.multiclass仍引用原状态对象,直接修改这些对象的属性属于React禁止的状态突变行为。 - 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
相关产品推荐
相关产品推荐

