Redux+React购物车增减数量后组件无法自动重渲染问题求助
问题根因
你遇到的组件不自动重渲染的问题,本质是违反了Redux reducer的不可变更新规则:
- Redux要求reducer是纯函数,禁止直接修改原state对象,必须返回全新的state副本
- 你的代码中对
state.Carts做了原地修改(调用push方法、直接修改数组项的quantity属性),虽然返回时用扩展运算符展开了state,但Carts数组的引用没有发生变化,React Redux的浅层比较检测不到数据变化,因此不会触发组件重新渲染。
修正方案
所有涉及Carts数组修改的逻辑,都要先拷贝原数组,在新数组上做修改,最终返回包含新Carts数组的state对象。以下是修正后的reducer核心逻辑:
const cartReducer=(state=initProductCart, action)=>{ switch(action.type){ case GET_ALL_PRODUCT: return{ ...state, } case GET_NUMBER_CART: return{ ...state, } case ADD_CART: // 先拷贝原购物车数组 const newCartsAdd = [...state.Carts]; if(state.numberCart==0){ let cart={ id:action.payload.id, quantity: 1, img:action.payload.img, name:action.payload.name, price:action.payload.price } newCartsAdd.push(cart) } else{ let check=false; newCartsAdd.forEach((item,key)=>{ if(item.id==action.payload.id){ // 拷贝对应商品项再修改数量 newCartsAdd[key] = { ...newCartsAdd[key], quantity: newCartsAdd[key].quantity + 1 } check=true; } }); if(!check){ let _cart={ id:action.payload.id, quantity: 1, img:action.payload.img, name:action.payload.name, price:action.payload.price } newCartsAdd.push(_cart) } } return { ...state, numberCart:state.numberCart+1, Carts: newCartsAdd } case INCREASE_QUANTITY: const newCartsInc = [...state.Carts]; newCartsInc[action.payload] = { ...newCartsInc[action.payload], quantity: newCartsInc[action.payload].quantity + 1 } return{ ...state, numberCart: state.numberCart + 1, Carts: newCartsInc } case DECREASE_QUANTITY: const newCartsDec = [...state.Carts]; let quantity= newCartsDec[action.payload].quantity; if(quantity>1){ newCartsDec[action.payload] = { ...newCartsDec[action.payload], quantity: newCartsDec[action.payload].quantity - 1 } return{ ...state, numberCart: state.numberCart - 1, Carts: newCartsDec } } // 数量不大于1时直接返回原state即可 return state; case DELETE_CART: let _quantity= state.Carts[action.payload].quantity; return{ ...state, numberCart:state.numberCart - _quantity, // 原逻辑filter返回新数组,符合不可变要求,无需修改 Carts: state.Carts.filter(item=>{ return item.id!=state.Carts[action.payload].id }) } default: return state; } }
其他注意事项
- 原代码中
map方法仅用来遍历修改数据,建议替换为语义更匹配的forEach方法 - 务必给reducer添加
default分支,返回原state,避免未知action导致state变为undefined
修改完成后,所有购物车操作都会生成新的Carts数组引用,Redux就能检测到数据变化,自动触发组件重渲染。
内容的提问来源于stack exchange,提问作者questioner
相关产品推荐
相关产品推荐

