React点击加入心愿单后setState执行两次属性被还原问题求解
两段代码的差异及问题原因
- React 18+ 开启
StrictMode严格模式时,传给setProducts的状态更新回调会被执行两次,这是React的内置机制,用于提前排查不纯的更新逻辑,你遇到的二次执行就是该机制导致的。
第一段代码异常的原因
你写的浅拷贝逻辑只生成了新的数组实例,数组内的商品对象仍和原始状态的商品对象共用同一份引用:
const latest_Products = [...prev]; // latest_Products 是新数组,但 latest_Products[x] 和 prev[x] 是同一个对象
直接修改latest_Products[selected_Prod_Id].inWishList相当于直接修改了原始状态的对象属性,属于非法的状态变更操作。第一次执行回调时原始状态的inWishList已经被改成true,第二次执行回调时拿到的prev是被第一次修改过的状态,再次取反就变回false,最终结果就不符合预期。
第二段代码正常的原因
第二段遵循了React的不可变更新原则,全程没有修改原始状态的任何值:
- 先基于原始状态计算好新的收藏状态
newFavStatus - 生成新数组后,给对应索引位置赋值了一个全新的商品对象,没有修改原状态里的对象:
updatedProducts[prodIndex] = { ...currentProdList[prodIndex], inWishList: newFavStatus, };
哪怕更新回调执行两次,两次都是基于最原始的currentProdList计算结果,返回的最终状态完全一致,不会出现值被重置的问题。
状态更新规范
所有引用类型状态(对象、数组、数组嵌套对象)更新时都要做不可变更新:修改对象属性就生成新对象,修改数组元素就生成新数组,如果修改的是数组内的对象,对应对象也要生成新实例,不要直接修改原始状态的值。
内容的提问来源于stack exchange,提问作者J.Tran
相关产品推荐
相关产品推荐

