Redux Store数组添加订单项时数据异常问题求助
问题分析与解决方案
问题描述
我正在开发一套收银系统,需要创建包含商品及对应售卖数量的订单列表,当前使用Redux Store进行状态管理。
遇到的问题:当触发ADDORDERITEM动作时,传入的action.order示例为{id: 1, name:"halve zolen", categoryId:1, price: 1.0},在该case中会将state.numberOfOrderItems赋值给newOrder.numberOfOrderItems。
单次添加商品时功能正常,但添加同一商品且输入不同数量时,最终订单数组中两个对象的数量均为最后一次输入的值,而预期应为两个不同的数量。检查赋值后的action.order是正确的,推测问题与使用state.numberOfOrderItems有关,想了解问题原因及如何获取其快照值不再被更新。
我的代码如下:
import {createStore} from 'redux'; const kassaReducer = (state = {orders: [], numberOfOrderItems: ""}, action) => { switch (action.type){ case "ADDORDERITEM": let newOrder = action.order; newOrder.numberOfOrderItems = state.numberOfOrderItems; return {orders: [...state.orders, newOrder], numberOfOrderItems: ""}; case "REMOVEORDERITEM": return {orders : state.orders.remove(state.orders.indexOf(action.order)), numberOfOrderItems: state.numberOfOrderItems}; case "SETITEMNUMBER": return {orders : state.orders, numberOfOrderItems: state.numberOfOrderItems === "" ? action.numberOfOrderItems : (state.numberOfOrderItems + action.numberOfOrderItems)}; } return state; } const store = createStore(kassaReducer); export default store;
问题原因
核心问题是直接修改了action.order的引用,而非创建新对象。Redux要求action保持不可变性,但你这里将newOrder指向了action.order的同一个引用,后续如果复用该原始商品对象(比如组件中同一商品的实例),之前添加到orders数组里的条目会因为引用相同,被后续的修改操作覆盖数值。
另外,state.numberOfOrderItems本身是值类型,赋值时确实拿到了当前状态的快照,但由于所有订单条目共享同一个对象引用,最后一次赋值的数量会同步到所有引用该对象的订单条目中。
解决方案
- 创建独立的订单对象,避免共享引用:在
ADDORDERITEM分支中,通过对象展开语法创建新对象,再附加数量属性,不直接修改原始action.order。 - 修正
REMOVEORDERITEM的数组操作:JavaScript数组没有remove方法,改用filter创建新数组,符合Redux不可变更新原则。 - 统一数量的数值类型:将
numberOfOrderItems初始值设为数字0,避免字符串拼接替代加法的问题。
修改后的代码:
import {createStore} from 'redux'; const kassaReducer = (state = {orders: [], numberOfOrderItems: 0}, action) => { switch (action.type){ case "ADDORDERITEM": // 基于原始商品对象创建新订单,独立引用 const newOrder = { ...action.order, numberOfOrderItems: state.numberOfOrderItems }; return { ...state, orders: [...state.orders, newOrder], numberOfOrderItems: 0 // 重置数量为初始值 }; case "REMOVEORDERITEM": // 过滤掉目标订单,返回新数组 return { ...state, orders: state.orders.filter(item => item !== action.order) }; case "SETITEMNUMBER": // 确保数量为数字类型,执行加法运算 const newNumber = typeof state.numberOfOrderItems === 'number' ? state.numberOfOrderItems + Number(action.numberOfOrderItems) : Number(action.numberOfOrderItems); return { ...state, numberOfOrderItems: newNumber }; } return state; } const store = createStore(kassaReducer); export default store;
关键说明
- 不可变性是Redux的核心原则,所有状态更新必须创建新对象/数组,不能直接修改原引用,这样才能保证每个订单条目独立,后续操作不会影响历史条目。
- 将数量初始值设为数字0,避免字符串类型导致的运算逻辑错误。
内容的提问来源于stack exchange,提问作者Amber Akkermans
相关产品推荐
相关产品推荐

