React中useReducer更新状态失效,直接修改属性和扩展运算符拷贝有何差异
问题核心原因
你的写法违反了React useReducer 要求的状态不可变更新原则,具体差异如下:
你的错误写法的问题
const updatedItem = state.items[existingCartItemIndex] 这行获取的是原state中items数组里对应对象的引用,后续你直接修改updatedItem.amount等同于直接修改了原state里的对象属性。
哪怕你后面用[...state.items]创建了新的数组,数组里存储的还是原来的对象引用,React做状态变更的浅对比时,检测不到对象的变化,就不会触发对应的组件重渲染,最终表现就是功能异常。
正确写法的逻辑
const updatedItem = {...existingCartItem, amount: existingCartItem.amount + action.item.amount} 是基于原有对象的属性,创建了一个全新的对象,和原state里的对象引用完全不同。
你把这个新对象放到新数组中后,整个新state的变更可以被React正常检测到,会触发对应的重渲染,功能就可以正常运行。
补充说明
React所有状态更新(包括useState、useReducer)都要求遵循不可变原则,禁止直接修改原状态的任何属性,所有变更都要创建新的副本:
- 基础类型直接返回新值即可
- 对象需要通过展开运算符
...复制原对象属性后,再修改对应字段 - 数组需要先创建新数组(用展开运算符、concat、filter等返回新数组的方法),如果数组元素是对象,对应要修改的元素也需要创建新对象
另外你代码里的toFixed返回的是字符串类型,建议统一totalAmount的类型,避免后续计算出现隐式类型转换问题。
内容的提问来源于stack exchange,提问作者amir_70
相关产品推荐
相关产品推荐

