简体   繁体   English

在 Redux 状态下调度不改变对象

[英]Dispatch not changing object in Redux state

So I'm building an ecommerce app, and I have two values stored in the redux state to handle the cart.所以我正在构建一个电子商务应用程序,并且我在 redux 状态中存储了两个值来处理购物车。 One is an array of objects, each of which contains two keys for objectID and quantity.一个是对象数组,每个对象包含对象 ID 和数量的两个键。 The other is an object containing product information with their objectID as a key.另一个是包含产品信息的对象,以它们的 objectID 为关键字。 Here's the code for my action/dispatch.这是我的行动/派遣的代码。

 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 }); }; },

The action definitely runs.动作肯定会跑。 Next up is my reducer.接下来是我的减速机。

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

That also executes, and indeed when inspecting the state, productQuantity is updated in state but products is not.这也会执行,并且确实在检查状态时, productQuantity 在 state 中更新,但 products 没有。 I've tried every configuration of definitions at this point and am tearing my hair out.在这一点上,我已经尝试了所有定义的配置,并且正在撕毁我的头发。 Help would be much appreciated.帮助将不胜感激。

What I can confirm:我可以确认的是:

  • Correct data is being dispatched to the reducer.正确的数据正在发送到减速器。
  • The reducer executes.减速器执行。
  • ProductQuantity is updated by the reducer correctly and has the correct value. ProductQuantity 由 reducer 正确更新并具有正确的值。

The first issue is that you're mutating the existing state before dispatching the action, and mutating state is forbidden in Redux :第一个问题是您在分派操作之前更改现有状态,并且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});
                }
            }

Any changes to productQuantity here are mutating the existing data in the Redux store.此处对productQuantity任何更改productQuantity改变 Redux 存储中的现有数据。 Don't do that.不要那样做。

I'm not quite clear on what's going on with products here, because the logic feels a bit confusing.我不太清楚这里的products发生了什么,因为逻辑感觉有点混乱。

My suggestions:我的建议:

First, start using our new official Redux Toolkit package .首先,开始使用我们新的官方 Redux Toolkit 包 It has a configureStore() function that automatically sets up detection for accidental mutations, and will throw errors if you mutate.它有一个configureStore()函数,可以自动设置对意外突变的检测,如果你发生突变,它会抛出错误。

Second, try to move all this modification logic into your reducer , instead of doing it on the action creation side.其次, 尝试将所有这些修改逻辑移动到您的 reducer 中,而不是在操作创建端进行。

Third, use Redux Toolkit's createSlice API , which uses the Immer library to to allow you to write "mutating" logic in your reducers and safely converts it into correct immutably-updated results.第三,使用 Redux Toolkit 的createSlice API ,它使用 Immer 库来允许您在减速器中编写“变异”逻辑,并将其安全地转换为正确的不可变更新结果。

Thanks to markerikson's response, I revised my action to treat Redux state immutably and the problem has been resolved.多亏了markerikson 的回应,我修改了我的操作以不变地处理Redux 状态,问题已经解决。 Here's my updated action for reference.这是我更新的操作以供参考。

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}])
            });
        };
    },

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM