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,当向购物车中添加一个新的物品时,代码正常运行;但当反复添加一个物品时,代码报出如下错误:

搜下资料发现是因为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新值,因此代码正常运行。

React redux toolkit: Uncaught Error:[Immer] An immer producer returned a new...的更多相关文章

  1. webpack+react+redux+es6开发模式---续

    一.前言 之前介绍了webpack+react+redux+es6开发模式 ,这个项目对于一个独立的功能节点来说是没有问题的.假如伴随着源源不断的需求,前段项目会涌现出更多的功能节点,需要独立部署运行 ...

  2. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  3. react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware

    今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...

  4. webpack+react+redux+es6

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  5. React Redux Sever Rendering实战

    # React Redux Sever Rendering(Isomorphic JavaScript) ![React Redux Sever Rendering(Isomorphic)入门](ht ...

  6. react+redux+generation-modation脚手架添加一个todolist

    当我遇到问题: 要沉着冷静. 要管理好时间. 别被bug或error搞的不高兴,要高兴,又有煅炼思维的机会了. 要思考这是为什么? 要搞清楚问题的本质. 要探究问题,探究数据的流动. TodoList ...

  7. 详解react/redux的服务端渲染:页面性能与SEO

        亟待解决的疑问 为什么服务端渲染首屏渲染快?(对比客户端首屏渲染)   react客户端渲染的一大痛点就是首屏渲染速度慢问题,因为react是一个单页面应用,大多数的资源需要在首次渲染前就加载 ...

  8. 实例讲解基于 React+Redux 的前端开发流程

    原文地址:https://segmentfault.com/a/1190000005356568 前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 s ...

  9. 【redux】详解react/redux的服务端渲染:页面性能与SEO

        亟待解决的疑问 为什么服务端渲染首屏渲染快?(对比客户端首屏渲染)   react客户端渲染的一大痛点就是首屏渲染速度慢问题,因为react是一个单页面应用,大多数的资源需要在首次渲染前就加载 ...

  10. 我的第一个 react redux demo

    最近学习react redux,先前看过了几本书和一些博客之类的,感觉还不错,比如<深入浅出react和redux>,<React全栈++Redux+Flux+webpack+Bab ...

随机推荐

  1. md文件使用说明

    md文件简单使用介绍 二级标题 三级标题 斜体文本 粗体文本 粗斜体文本 分隔线 删除号 带下划线 创建脚注格式类似这样 [1]. #include <iostream> using na ...

  2. github 开源项目安装

    1.打开github 2.搜索相关项目 3.使用系统下载安装 4.执行 指令;git clone git://github.com/****.git

  3. golang sync.Once用法

    sync.Once能确保实例化对象Do方法在多线程环境只运行一次,内部通过互斥锁实现 Do方法 Once类型的Do方法只接收一个参数,参数的类型必须是func(),即无参数无返回的函数.该方法的功能并 ...

  4. java map重写 转大写、转驼峰

    /** * @author admin * @Description * 转大写 */ public class HashMapUpper<V> extends HashMap<St ...

  5. C#获取本地所有打印机名称

    引用:using System.Drawing.Printing; 实现代码: List<string> PrintS = new List<string>(); foreac ...

  6. Visual Studio 2019 专业版许可证过期解决办法

    Visual Studio 2019 许可证过期,登录微软账户也不行,一直提示点击更新许可证,"无法下载许可证,请检查你的网络连接或代理设置" 解决方案:找到VS2019安装目录, ...

  7. 面试-JVM

    1.java内存模型 / java运行时数据区模型? 元空间属于本地内存 而非JVM内存 内存模型 程序计数器 1.作为字节码的行号指示器,字节码解释器通过程序计数器来确定下一步要执行的字节码指令,比 ...

  8. Tensorflow Debug Record

    problem: InternalError (see above for traceback): Blas GEMM launch failed solve: sudo rm -rf ~/.nv/ ...

  9. 在POD的ENV中添加POD的信息

    主要用到的参数: - name POD_NAME volumeFrom: fieldRef: fieldPath:   metadata.name - name: POD_IP volumeFrom: ...

  10. C# Set集合

    包含不重复元素的集合称为"集(set)"..NET Framework包含两个集HashSet<T>和SortedSet<T>,它们都实现ISet<T ...