React redux toolkit: Uncaught Error:[Immer] An immer producer returned a new…

  • React redux toolkit: Uncaught Error:[Immer] An immer producer returned a new…已关闭评论
  • 272 次浏览
  • A+
所属分类:Web前端
摘要

React在写一个购物车的redux toolkit时遇到了问题。核心代码如下:核心逻辑是,调用addProduct来修改redux所管理的cartItems和cartItemCount,当向购物车中添加一个新的物品时,代码正常运行;但当反复添加一个物品时,代码报出如下错误:

React在写一个购物车的redux toolkit时遇到了问题。核心代码如下:

import { createSlice } from "@reduxjs/toolkit";  const cartSlice = createSlice({     name: 'cart',     initialState: {         cartItems: [],         cartItemCount: 0     },     reducers: {         addProduct(state, action) {             const { imageUrl, name, price } = action.payload             let newCartItems = [...state.cartItems]              let flag = newCartItems.some((item, index, arr) => {                 if(item.name == name) {                     arr[index].quantity += 1                     return true                 }             })              if(!flag) {                 newCartItems = [                      ...state.cartItems,                     { imageUrl, name, price, quantity: 1 }                  ]             }              const cartItemCount = newCartItems.reduce(                 (prevTotal, currItem) =>  prevTotal + currItem.quantity, 0             )             return { cartItems: newCartItems, cartItemCount }         }     } })  export const { addProduct, deleteProduct, incQuantity, decQuantity } = cartSlice.actions export default cartSlice.reducer  

核心逻辑是,调用addProduct来修改redux所管理的cartItems和cartItemCount,当向购物车中添加一个新的物品时,代码正常运行;但当反复添加一个物品时,代码报出如下错误:

React redux toolkit: Uncaught Error:[Immer] An immer producer returned a new...

搜下资料发现是因为redux使用immer,不允许在reducer中修改state值后还return,二者只能取其一。

因此,当添加一个新物品时,由于没有修改cartItems,因此可以有返回值,不报错。

但当添加一个重复的物品时,即使在最开始使用了let newCartItems = [...state.cartItems]来创建一个新的对象,但由于state.cartItems数组中保存的不是基本数据类型,而是一个对象,因此newCartItems保存的是state.cartItems中各个对象的引用,即

newCartItems == state.cartItems  // false newCartItems[0] == state.cartItems[0]  // true 

由此可得,添加一个新物品时,由于既修改了state,又return了新值,因此报出immer错误。

修改后的代码如下:

addProduct(state, action) {     const { imageUrl, name, price } = action.payload      let flag = state.cartItems.some((item, index, arr) => {         if(item.name == name) {             arr[index].quantity += 1             state.cartItemCount += 1             return true         }     })      if(!flag) {         state.cartItems.push({ imageUrl, name, price, quantity: 1 })         state.cartItemCount += 1     } } 

这里只是对state做了修改,而没有return新值,因此代码正常运行。