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

image.png

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

作者:|ruoyxue|,原文链接: https://www.cnblogs.com/ruoyxue/p/17327979.html

文章推荐

表达式求值

RocketMQ 顺序消费机制

Github Copilot Chat 初体验

解析内存中的高性能图结构

MySQL大量脏数据,如何只保留最新的一条?

spring boot过滤器实现项目内接口过滤

v-if与v-show造成部分元素丢失的问题——v-if复用元素问题

Redis集群介绍及测试思路

golang中关于死锁的思考与学习

深入理解 Python 虚拟机:浮点数(float)的实现原理及源码...

聊聊C#中的Mixin

探究MySQL中SQL查询的成本