单设备多账户电商购物车Redux实现:state.carts[ID]未定义问题
问题与修复方案
我开发了一个电商网站,想要实现单台电脑上多账户切换时显示对应账户的购物车商品,写了如下Redux代码:
const initialState = { carts: {}, }; const cartSlice = createSlice({ name: "profile", initialState, reducers: { addToCart: (state, action) => { if (state.carts[action.payload.id]) { const itemExists = state.carts[action.payload.id].find( (item) => item.id === action.payload.id ); if (itemExists) { itemExists.quantity++; } else { state.carts[action.payload.id].push({ ...action.payload.item, quantity: 1, }); } toast(`${action.payload.title} added`); } else { return { ...state, carts: { ...state.carts, [action.payload.id]: [ ...state.carts[action.payload.id], { ...action.payload.item, quantity: 1 }, ], }, }; } }, incrementQuantity: (state, action) => { const item = state.cart.find((item) => item.id === action.payload); item.quantity++; }, decrementQuantity: (state, action) => { const item = state.cart.find((item) => item.id === action.payload); if (item.quantity === 1) { const index = state.cart.findIndex( (item) => item.id === action.payload ); state.cart.splice(index, 1); } else { item.quantity--; } }, removeFromCart: (state, action) => { const index = state.cart.findIndex((item) => item.id === action.payload); state.cart.splice(index, 1); }, }, });
组件中调用addToCart的代码:
onClick={() => dispatch( addToCart({ item, id: data.user.user.id, }) ) }
现在遇到错误:state.carts[action.payload.id]未定义,期望的最终状态结构是:
{ carts:{ id1:[shopping carts items], id2:[shopping carts items], ... } }
错误原因与修复
1. addToCart分支的展开错误
在else分支中,...state.carts[action.payload.id]会尝试展开一个undefined(因为此时该用户id对应的购物车还不存在),直接导致报错。同时商品存在性判断混淆了用户id和商品id,应该用action.payload.item.id去匹配购物车中的商品。
2. 其他reducer的状态引用错误
incrementQuantity、decrementQuantity、removeFromCart中都错误引用了state.cart(单数),但实际状态结构是state.carts(复数),且没有指定操作的用户id,无法定位到对应账户的购物车。
修正后的完整代码
const initialState = { carts: {}, }; const cartSlice = createSlice({ name: "profile", initialState, reducers: { addToCart: (state, action) => { const { id: userId, item } = action.payload; // 先获取当前用户的购物车,不存在则初始化为空数组 const userCart = state.carts[userId] || []; // 用商品id判断是否已存在 const itemExists = userCart.find(cartItem => cartItem.id === item.id); if (itemExists) { itemExists.quantity++; } else { userCart.push({ ...item, quantity: 1 }); } // 直接更新state(Immer支持这种修改方式) state.carts[userId] = userCart; toast(`${item.title} added`); }, incrementQuantity: (state, action) => { const { userId, itemId } = action.payload; const userCart = state.carts[userId]; if (!userCart) return; const targetItem = userCart.find(item => item.id === itemId); if (targetItem) targetItem.quantity++; }, decrementQuantity: (state, action) => { const { userId, itemId } = action.payload; const userCart = state.carts[userId]; if (!userCart) return; const targetItem = userCart.find(item => item.id === itemId); if (!targetItem) return; if (targetItem.quantity === 1) { const index = userCart.findIndex(item => item.id === itemId); userCart.splice(index, 1); } else { targetItem.quantity--; } }, removeFromCart: (state, action) => { const { userId, itemId } = action.payload; const userCart = state.carts[userId]; if (!userCart) return; const index = userCart.findIndex(item => item.id === itemId); if (index !== -1) userCart.splice(index, 1); }, }, });
组件调用更新
其他购物车操作(如增减数量)需要同时传入用户id和商品id,示例:
// 增加商品数量 onClick={() => dispatch( incrementQuantity({ userId: data.user.user.id, itemId: item.id, }) ) }
内容的提问来源于stack exchange,提问作者Negar Nasiri
相关产品推荐
相关产品推荐

