簡體   English   中英

盡管使用擴展運算符進行 state 復制,但 Redux state 突變

[英]Redux state mutation despite making state copy with spread operator

為什么我在使用擴展運算符制作 object 的副本時收到 state 突變警報? 我正在嘗試使用 redux 制作購物車。 當添加一個元素或減少它的數量時,我會發送一個更新 de state 的操作。 如果尚未添加產品,則在我的減速器中,我返回 state 數組的新副本,其中包含新的 object。 如果它已經被添加,我將使用 map (返回一個新數組)和我正在增加的產品副本進行迭代,並且它的qty屬性增加了。 問題在於此屬性 在不改變 state 的情況下更新此屬性的正確方法是什么?

減速器

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"....}

正在改變當前項目。 前/后遞增/遞減將改變它操作的當前 object 參考。

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

我懷疑您的代碼按預期運行,因為您確實正確替換了整個購物車數組,並且您變異的項目是您想要更新的項目,但這表明您的減速器可能不是純 function,即之前的 state 應該仍然在減速器計算下一個 state之后,在所有方面都等於之前的 state。

看起來您正在使用我們的官方 Redux 工具包 package ,默認情況下會警告意外的 state 突變。 太好了,因為在這種情況下它顯然捕獲了一個突變。

但是,更好的是Redux Toolkit 使用 Immer inside 讓您在減速器中編寫“變異” state 更新! . 這意味着您的減速器邏輯可以簡化為:

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

我做了幾次這樣的事情,試試這個代碼:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM