调度不更改Redux状态下的对象

时间:2020-01-22 17:18:28

标签: javascript reactjs redux redux-saga redux-thunk

因此,我正在构建一个电子商务应用程序,并且在redux状态下存储了两个值来处理购物车。一个是对象数组,每个对象包含两个用于objectID和数量的键。另一个是包含产品信息的对象,其对象ID为键。这是我的动作/调度的代码。

addToCart: (product) => {
        return (dispatch, getState) => {
            const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
            const UPC = product.UPC;
            let newQuant = 1;
            let newProducts;
            for(var p in productQuantity) {
                if (productQuantity[p].UPC === UPC) {
                    newProducts = products
                    newQuant += productQuantity[p].quantity;
                    productQuantity[p] = ({UPC, quantity: newQuant});
                }
            }
            if (!newProducts) {
                console.log("not found")
                productQuantity.push({UPC, quantity: 1});
                newProducts = {
                    ...products,
                    [UPC]: {
                        ...product,
                        price: product.stores[storeKeys[storeSelected]].price,
                        fromStore: storeKeys[storeSelected],
                    }
                }
            }
            dispatch({
                type: actions.CHANGE_CART,
                products: newProducts,
                productQuantity
            });
        };
    },

该动作肯定会运行。接下来是我的减速器。

case actions.CHANGE_CART:
    console.log('This runs')
    console.log(action.products);
    console.log(action.productQuantity);
    return {
        ...state,
        products: action.products,
        productQuantity: action.productQuantity
    };

这也将执行,实际上在检查状态时,productQuantity会在状态中更新,而产品不会。此时,我已经尝试了定义的每种配置,并且正在扯头发。帮助将不胜感激。

我可以确认的内容:

  • 正确的数据正被分派到化简器。
  • 减速器执行。
  • ProductQuantity由reducer正确更新,并具有正确的值。

2 个答案:

答案 0 :(得分:0)

第一个问题是您在分派操作之前先更改现有状态,然后mutating state is forbidden in Redux

const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
            const UPC = product.UPC;
            let newQuant = 1;
            let newProducts;
            for(var p in productQuantity) {
                if (productQuantity[p].UPC === UPC) {
                    newProducts = products
                    newQuant += productQuantity[p].quantity;
                    productQuantity[p] = ({UPC, quantity: newQuant});
                }
            }

此处对productQuantity的任何更改都会使Redux存储中的现有数据发生变异。不要那样做。

我不太清楚products的情况,因为逻辑上有些混乱。

我的建议:

首先,开始使用our new official Redux Toolkit package。它具有configureStore()功能,可以自动设置对意外突变的检测,如果您突变,则会抛出错误。

第二,try to move all this modification logic into your reducer,而不是在动作创建端进行。

第三,使用Redux Toolkit的createSlice API,该工具使用Immer库允许您在化简器中编写“变异”逻辑并将其安全地转换为正确的不可变更新结果。

答案 1 :(得分:0)

多亏了markerikson的回应,我修改了我的行动以一成不变地对待Redux状态,问题已得到解决。这是我更新的操作,仅供参考。

addToCart: (product) => {
        return (dispatch, getState) => {
            const {productQuantity, storeSelected, products, storeKeys} = getState().Ecommerce;
            const UPC = product.UPC;

            let newQuantity = 1;
            for(var p in productQuantity) {
                if (productQuantity[p].UPC === UPC) {
                    newQuantity += productQuantity[p].quantity;
                }
            }

            dispatch({
                type: actions.CHANGE_CART,
                products: {
                    ...products,
                    [UPC]: {
                        ...product,
                        price: product.stores[storeKeys[storeSelected]].price,
                        fromStore: storeKeys[storeSelected],
                    }
                },
                productQuantity: productQuantity
                    .filter((value, index) => value.UPC !== product.UPC)
                    .concat([{UPC, quantity: newQuantity}])
            });
        };
    },