React对象类型状态更新:三种方式的有效性与选型对比
React对象状态更新的三种写法:有效性与选择理由
一、三种写法的有效性
第一种写法有效:
setFormData(Object.assign({}, formData, {b: 22}));Object.assign会先创建空对象,把formData的所有属性拷贝过去,再覆盖b的值为22,最终返回全新对象,完全满足React状态更新必须传递新引用的要求。第二种写法有效:
setFormData((prevData) => ({ ...prevData, b: 22 }));这是React推荐的函数式更新写法:React会自动把当前最新状态传给
prevData参数,我们用ES6扩展运算符浅拷贝旧状态,再更新b属性并返回新对象。这种方式能确保拿到最新状态,避免闭包捕获旧值导致的错误。第三种写法无效:
setFormData( { ...prevData, "b": 22 } )这里的
prevData是未定义的变量,直接写会抛出ReferenceError。React不会自动把状态值注入到普通对象字面量中,必须通过函数式更新的回调参数才能获取prevData。
二、选择不同写法的理由
选Object.assign的情况
- 需要兼容不支持ES6扩展运算符的老旧环境时,
Object.assign作为ES5标准API,兼容性更好 - 当需要合并多个源对象时,
Object.assign可一次性传递多个参数(比如Object.assign({}, obj1, obj2, obj3)),写法比多次使用扩展运算符更简洁
选函数式更新(箭头函数+扩展运算符)的情况
- 当状态更新依赖前一次状态时,必须用这种写法。比如连续点击按钮累加数值、在定时器/API回调里更新状态,函数式更新能保证每次拿到的都是最新状态,避免闭包导致的旧值问题
- 日常开发中,扩展运算符的写法比
Object.assign更直观、可读性更高,尤其是仅更新少数属性的场景
第三种写法为什么不能用
核心原因是prevData未定义,React不会自动生成这个变量。如果想用扩展运算符更新状态,必须将其放入函数式更新的回调中,参考第二种写法的格式。
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

