【问题标题】:Why Immer didn't return me a new state even if I modified the draft?为什么即使我修改了草稿,Immer 也没有给我返回一个新的状态?
【发布时间】:2020-11-21 20:19:01
【问题描述】:

我不知道为什么我连草稿都修改了,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;

当新项目被推入数组时它正在工作,但是当我想修改数组项目的数量和总和时它没有按预期工作。日志显示在这种情况下它是同一个对象。

【问题讨论】:

  • 也许您应该在produce 回调中从draftState 中找到项目ID。在produce 回调中,在条件之前尝试const itemIndexInCart = draftState.findIndex(item => item.id === id);
  • 不,它不起作用,实际上 nextState 已更新,但不知何故它共享了对状态的内存引用。

标签: reactjs redux immer.js


【解决方案1】:

根据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

【讨论】:

    【解决方案2】:

    注意you should never put non-serializable values like class instances into the Redux store

    此外,您应该使用our official Redux Toolkit package,这将让您简化现有的 Redux 逻辑。例如,这个 reducer 可以写成:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-17
      • 2020-07-03
      • 2021-09-06
      • 2021-11-25
      • 2022-07-12
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      相关资源
      最近更新 更多