Почему Immer не вернул мне новое состояние, даже если я изменил черновик? - PullRequest
3 голосов
/ 01 августа 2020

Я не знаю, почему даже я изменил черновик, immer предоставил мне не новое состояние, а старый экземпляр состояния с измененным содержимым.

import CartItem from "../../models/cart-item";
import * as actions from "../actions/actionTypes";
import produce from "immer"


const initialState = [];

const reducer = (state=initialState, action) => {
    switch (action.type) {
        case actions.ADD_TO_CART:
          const {id, title, price} = action.product;
          const itemIndexInCart = state.findIndex(item => item.id === id);

          const nextState = produce(state, draftState => {
            if (itemIndexInCart === -1) {
              draftState.push(new CartItem(id, 1, price, title, price));
            } else {
              draftState[itemIndexInCart]['quantity']++;
              draftState[itemIndexInCart]['sum'] += price;
            }
          });
          console.log(state === nextState);
          return nextState;
        default:
            return state;
    }
};

export default reducer;

Он работает, когда новый элемент помещается в массив, но он не работает должным образом, когда я хочу изменить количество и сумму элемента массива. Журнал показывает мне, что при данных обстоятельствах это тот же объект.

Ответы [ 2 ]

1 голос
/ 01 августа 2020

Уловка состоит в том, чтобы сделать ваш класс непроницаемым , согласно docs . Обратите внимание, что console.logging черновика может выводить «null», даже если этот объект не равен null.

import {immerable} from "immer"

class Foo {
    [immerable] = true // Option 1

    constructor() {
        this[immerable] = true // Option 2
    }
}

Foo[immerable] = true // Option 3

Рабочая демонстрация: https://codesandbox.io/s/blissful-resonance-v6v9b?file= / src / App. js

0 голосов
/ 02 августа 2020

Обратите внимание, что вам не следует никогда помещать несериализуемые значения, такие как экземпляры классов, в хранилище Redux .

Кроме того, вы должен использовать наш официальный пакет Redux Toolkit , который позволит вам упростить ваш существующий Redux logi c. Например, этот редуктор можно записать как:

const cartSlice = createSlice({
  name: "cart",
  initialState: [],
  reducers: {
    addToCart(state, action) {
      const {id, title, price} = action.payload;
      const item = state.find(item => item.id === id);
      
      if(item) {
        item.quantity++;
        item.sum += price;
      } else {
        state.push({id, price, title, quantity: 1});
      }
    }
  }
})
...