Redux Toolkit reducer中if/else未按id+size匹配规则正常工作
购物车Redux逻辑异常问题
需求与问题现象
- 预期实现逻辑:
- 购物车已存在同ID同尺码的商品时,对应商品数量加1
- 添加同ID不同尺码的同款商品时,作为独立条目单独展示
- 异常表现:代码中已经添加了同时匹配商品ID与size的
find查找条件,但实际运行时仅校验商品ID就执行数量递增,未校验size属性。
问题相关原代码如下:
import { createSlice } from "@reduxjs/toolkit"; const initialState = { bagData: [], }; export const bagDataSlice = createSlice({ name: "bagDataProducts", initialState, reducers: { sendDataToCardComponent: (state, action) => { let { id, size } = action.payload; const findItemById = state.bagData.find( (item) => item.id === id && item.size === size ); if (findItemById) { state.bagData.filter((item, i) => (state.bagData[i].quantity += 1)); } else { state.bagData.push({ ...action.payload, quantity: 1 }); } }, increaseItemQuantity: (state, { payload }) => { state.bagData.filter((item, i) => item.id === payload ? (state.bagData[i].quantity += 1) : item ); }, decreaseItemQuantity: (state, { payload }) => { state.bagData.filter((item, i) => item.id === payload && item.quantity > 1 ? (state.bagData[i].quantity -= 1) : item ); }, removeItem: (state, { payload }) => { state.bagData = state.bagData.filter((item) => item.id !== payload); }, }, });
问题产生原因
- 匹配成功后的递增逻辑完全写错:你用
find确实正确匹配到了同ID同尺码的商品,但进入if (findItemById)分支后,调用filter遍历购物车数组时没有加任何判断条件,遍历到每一个商品都会执行quantity +=1,等于给购物车所有商品数量都加1,根本没有操作你之前找到的目标匹配项。 - 后续数量增减、删除逻辑本身就没有做尺码校验:
increaseItemQuantity、decreaseItemQuantity、removeItem三个方法都只判断了商品ID,完全没有接收size参数做匹配,同ID下所有尺码的商品会被同时修改数量、同时删除,本身就不符合独立条目的设计要求。 - 方法误用:
filter的作用是按条件筛选返回新数组,不适合用来做遍历修改操作,无意义的遍历和返回值会增加额外性能开销,也容易引发逻辑错误。
修复方案
直接操作已经找到的匹配项修改数量,同时所有涉及商品操作的reducer都同时校验ID和size两个字段,修复后代码如下:
import { createSlice } from "@reduxjs/toolkit"; const initialState = { bagData: [], }; export const bagDataSlice = createSlice({ name: "bagDataProducts", initialState, reducers: { sendDataToCardComponent: (state, action) => { const { id, size } = action.payload; // 匹配同ID同尺码商品 const existItem = state.bagData.find( (item) => item.id === id && item.size === size ); if (existItem) { // 直接给匹配到的商品数量+1,不需要全量遍历 existItem.quantity += 1; } else { state.bagData.push({ ...action.payload, quantity: 1 }); } }, // 入参需要同时传id和size increaseItemQuantity: (state, { payload }) => { const { id, size } = payload; const targetItem = state.bagData.find(item => item.id === id && item.size === size); if (targetItem) targetItem.quantity += 1; }, decreaseItemQuantity: (state, { payload }) => { const { id, size } = payload; const targetItem = state.bagData.find(item => item.id === id && item.size === size); if (targetItem && targetItem.quantity > 1) targetItem.quantity -= 1; }, removeItem: (state, { payload }) => { const { id, size } = payload; // 删除时同时匹配id和size,只删对应尺码的条目 state.bagData = state.bagData.filter(item => !(item.id === id && item.size === size)); }, }, }); export const { sendDataToCardComponent, increaseItemQuantity, decreaseItemQuantity, removeItem } = bagDataSlice.actions; export default bagDataSlice.reducer;
注意:调用后面三个增减、删除方法时,dispatch的payload需要同时传入商品的id和size两个参数,才能精准定位到对应尺码的商品条目。
内容的提问来源于stack exchange,提问作者Berke Palamutcu
相关产品推荐
相关产品推荐

