React:setState更新状态时被调用两次的问题排查
首先明确:React的StrictMode在开发环境下会两次调用状态更新函数(即setFormData的回调函数),这是官方设计行为,目的是检测更新函数是否为纯函数(是否存在副作用、是否依赖外部可变状态)。
你的第一种写法和第二种写法逻辑上等价,但第一种写法的问题出在中间对象的修改步骤上——虽然你做了浅拷贝,但这种“先创建中间对象、再修改其属性”的写法,在StrictMode的两次调用检测中,容易让你误以为状态被更新了两次,但实际上只是更新函数被执行了两次,并非真正的两次状态变更。
你提到第二种写法解决了问题,核心原因在于:
第二种写法直接通过对象展开运算符{...prev, ...}创建并返回新状态对象,没有任何中间对象的修改操作,完全符合React对纯函数更新的预期。而第一种写法中,你先创建spread对象再修改其features属性,虽然逻辑正确,但这种“先创建后修改”的模式,可能在StrictMode的检测逻辑中被误判为潜在不纯操作(尽管你的更新函数实际是纯函数),或者让你通过console.log的两次输出误解为状态异常。
另外,第一种写法存在冗余操作:spread.features = [...features]里的[...features]完全多余,因为features已经是通过扩展运算符或filter生成的新数组,直接赋值spread.features = features即可。
总结来说,两种写法的状态更新结果完全一致,你看到的“setState触发两次”是StrictMode的正常行为;第二种写法解决了你感知到的问题,是因为它更简洁地遵循了React的状态更新规范,避免了中间对象修改带来的混淆。
内容的提问来源于stack exchange,提问作者Aousaf Rashid

