React中数组push与扩展运算符的差异及异常问题咨询
React数组状态更新重复添加的原因与避坑指南
为什么第一个代码会出现[10,10]?
1. 直接修改了React状态的原数组
React要求状态是不可变的——你不能直接修改useState返回的原状态值,必须返回新的值来触发正确更新。数组是引用类型,prevArr.push(10)是原地修改原数组,等于直接篡改了React内部维护的状态数据,这违反了React的状态管理规则。
2. 开发模式的严格模式在检测违规
React开发模式下的Strict Mode会两次调用状态更新函数,专门用来检测开发者是否违反不可变原则:
- 第一次调用:
prevArr是初始空数组,push(10)后变成[10]并返回。 - 第二次调用:此时原状态数组已经被改成
[10],再次push(10)就变成[10,10]并返回。
最终状态就变成了[10,10]。
而正确的代码用[...prevArr, 10]创建了全新数组,更新函数是纯函数(不会修改入参,只返回新值),哪怕被调用两次,每次都是基于传入的prevArr生成新数组,React会正确处理,最终得到预期的[10]。
需警惕的类似场景
- 引用类型状态的原地修改:不管是对象还是数组,别用
push/pop/splice/obj.key = val这类原地修改方法,必须返回新的对象或数组(比如用扩展运算符、Object.assign、数组map/filter等返回新值的方法)。 - 非纯状态更新函数:别在更新函数里修改入参、依赖外部可变变量,比如
setState(prev => { prev.count++; return prev; })这种写法绝对要避免。 - 第三方库操作状态:用第三方库处理状态时,确保返回新值而非修改原状态,比如用深复制方法复制对象后再修改,而不是直接篡改原对象。
内容的提问来源于stack exchange,提问作者Satyam Mishra
相关产品推荐
相关产品推荐

