如何使用 immer.js 更新多个状态属性

How to update multiple state properties with immer.js

我想知道是否可以在 "call".

中使用 immer.js 更新状态的多个属性

假设我有 state:

export const initialState = {
  isUserLogged: false,
  menuIsClosed: false,
  mobileMenuIsClosed: true,
  dataArray: ["dog","cat"],
};

action creator

export function updateSearchPage(data) {
  return {
    type: UPDATE_SEARCH_PAGE,
    payload: data
  };
}

然后我像这样在 React 组件中使用 action creator

  this.props.updateSearchPage({
    isUserLogged: true,
    menuIsClosed: true,
    dataArray: ["dog","cat","owl"]
  })

我的想法是同时更新状态的几个属性。但是我不知道它是什么属性。我知道如何使用简单的减速器来做到这一点:

case UPDATE_SEARCH_PAGE:
  return Object.assign({}, state, action.payload)

但是how to update several properties of state with immer at the same time?当状态属性(应该更新哪个)提前 未知

Immer 为您提供可以编辑的草稿状态。在幕后,它使用 ES6 代理来发现您更改的内容,并以不可变的方式将您的编辑应用到原始状态。

基本上,您可以做与现在完全相同的事情,但是使用 Immer api:

import produce from 'immer'

const newState = produce(this.state, draft => Object.assign({}, draft, payload))

如果您知道更改了哪些属性,则可以执行以下操作:

const newState = produce(this.state, draft => {
  draft.propertyOne = 'newValue'
  draft.propertyTwo = 42
})

您可以像下面这样在 action.payload 上循环:

const yourReducer = (state, action) =>
  produce(state, draft => {
    switch (action.type) {
      case UPDATE_SEARCH_PAGE:
        Object.entries(action.payload).forEach(([k, v]) => {
          draft[k] = v;
        })
        break;
    // ... other
    }
  }

此外:请记住,在最新版本的 immer 中,returns 对象是完全合法的,因此 return Object.assign({}, state, action.payload)produce 调用中仍然有效。

在 ES6 中你可以这样做:

export const state = produce((draft, action) => {
  switch (type) {
    case UPDATE_SEARCH_PAGE:
      return {...draft, ...action.payload}
  }
}, initialState)

在这种情况下,它的工作方式与没有 Immer 的情况相同。所有属性都将合并(浅合并)到状态中。如果你需要更换状态只是 return action.payload