为了账号安全,请及时绑定邮箱和手机立即绑定

尽管使用传播运算符进行状态复制,但仍存在 Redux 状态突变

尽管使用传播运算符进行状态复制,但仍存在 Redux 状态突变

杨__羊羊 2022-09-02 21:10:59
为什么我在使用传播运算符复制对象时收到状态突变警报?我正在尝试用redux制作一个购物车。当添加元素或减少其数量时,我会调度一个更新 de 状态的操作。在我的化简器中,如果尚未添加产品,我将返回带有新对象的状态数组的新副本。如果已经添加了它,我将使用map(返回一个新数组)和我正在增加的产品的副本进行迭代,并且其属性增加。问题是此属性 在不改变状态的情况下更新此属性的正确方法是什么?qty还原剂case types.ADD_TO_CART_SUCCESS:  const isAdded = state.cart.find(item => item.sku === action.product.sku);  if (!isAdded) action.product.qty = 1;  return {    ...state,    cart: !isAdded      ? [action.product, ...state.cart]      : state.cart.map(item =>          item.sku === action.product.sku            ? { ...item, qty: ++item.qty }            : item        ),  };违规警告Invariant Violation: A state mutation was detected inside a dispatch, in the path: `user.cart.0.qty`. Take a look at the reducer(s) handling the action {"type":"ADD_TO_CART_SUCCESS"....}
查看完整描述

3 回答

?
www说

TA贡献1775条经验 获得超8个赞

您正在改变当前项。前/后递减/递减将改变它所操作的当前对象引用。


case types.ADD_TO_CART_SUCCESS:

  const isAdded = state.cart.find(item => item.sku === action.product.sku);

  if (!isAdded) action.product.qty = 1;

  return {

    ...state,

    cart: !isAdded

      ? [action.product, ...state.cart]

      : state.cart.map(item =>

          item.sku === action.product.sku

            ? { ...item, qty: ++item.qty } // <-- This mutates the current item.qty

            : item

        ),

  };

但是,您可以返回递增的值,当前item.qty + 1


case types.ADD_TO_CART_SUCCESS:

  const isAdded = state.cart.find(item => item.sku === action.product.sku);

  if (!isAdded) action.product.qty = 1;

  return {

    ...state,

    cart: !isAdded

      ? [action.product, ...state.cart]

      : state.cart.map(item =>

          item.sku === action.product.sku

            ? { ...item, qty: item.qty + 1 }

            : item

        ),

  };

我怀疑您的代码按预期运行,因为您确实正确替换了整个购物车数组,并且您变异的项目是您想要更新的项目,但这表明您的化简器可能不是纯函数,即在化简器计算下一个状态后,先前的状态在所有方面仍应等于先前的状态。


查看完整回答
反对 回复 2022-09-02
?
Helenr

TA贡献1780条经验 获得超4个赞

看起来您正在使用我们的官方 Redux Toolkit 包,默认情况下,该包将警告意外状态突变。这很好,因为它显然在这种情况下发现了一个突变。

但是,更好的是,Redux Toolkit在内部使用Immer来让你在化简器中编写“变异”状态更新!这意味着您的化简器逻辑可以简化为:

const cartSlice = createSlice({

  name: 'cart',

  initialState,

  reducers: {

    addToCartSuccess(state, action) {

      const item = state.cart.find(item => item.sku === action.payload.product.sku);

      if (item) {

        item.qty++;

      } else {

        action.product.qty = 1;

        state.cart.unshift(action.payload.product);

      }

    }

  }

})


查看完整回答
反对 回复 2022-09-02
?
慕仙森

TA贡献1827条经验 获得超8个赞

我做了几次这样的东西,试试这个代码:


const addItemToCart = (cartItems, cartItemToAdd) => {

  const existingCartItem = cartItems.find(

    (cartItem) => cartItem.id === cartItemToAdd.id

  );


  if (existingCartItem) {

    return cartItems.map((cartItem) =>

      cartItem.id === cartItemToAdd.id

        ? { ...cartItem, quantity: cartItem.quantity + 1 }

        : cartItem

    );

  }


  return [...cartItems, { ...cartItemToAdd, quantity: 1 }];

};


查看完整回答
反对 回复 2022-09-02
  • 3 回答
  • 0 关注
  • 171 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号