简体   繁体   English

Redux 减速器 state 突变和恢复初始 state

[英]Redux reducer state mutations and restoring initial state

What's the best way to restore initial state?恢复初始 state 的最佳方法是什么? For this example let's say I can edit a car by dispatching the following actions:对于此示例,假设我可以通过调度以下操作来编辑汽车:

dispatch(actions.editModel('Civic'));

dispatch(actions.editType({
    make: 'Ford',
    model: 'Focus'
}));

dispatch(actions.restoreInitialState());

My reducer looks like this:我的减速器看起来像这样:

const initialState = {
  id: '1',
  vehicle: 'car',
  type: {
    make: 'Honda',
    model: 'Accord'
  },
  license: 'abc'
}

export default createReducer({
  [actions.editType]: (state, payload) => ({
    ...state,
    type: payload // payload is an object
  }),
  [actions.editModel]: (state, payload) => ({
    ...state,
    type: {
      ...state.type,
      model: payload // payload is a string
    }
  }),
  [actions.restoreInitialState]: (state) => ({
    state: initialState // initial state has nested objects
  })
}, initialState)

Is there a risk I am mutating my state or restoring my initial state incorrectly?我是否有风险改变我的 state 或错误地恢复我的初始 state? This might be overkill but I was thinking of editing my reducers like this:这可能有点矫枉过正,但我正在考虑像这样编辑我的减速器:

export default createReducer({
  [actions.editType]: (state, payload) => ({
    ...state,
    type: { 
        ...payload // payload is an object
    }
  }),
  [actions.editModel]: (state, payload) => ({
    ...state,
    type: {
      ...state.type,
      model: payload // payload is a string
    }
  }),
  [actions.restoreInitialState]: (state) => ({
    state: {
        ...initialState // initial state has nested objects
    }
  })
}, initialState)

Is there a difference when I'm passing an object through the payload vs just referencing my initial state?当我通过有效负载传递 object 与仅引用我的初始 state 时有区别吗? (Plus my initial state contains nested objects) (加上我最初的 state 包含嵌套对象)

You've got a great question.你有一个很好的问题。 And to answer this, you need to think about why its so important to avoid mutating data in React.要回答这个问题,您需要考虑为什么避免在 React 中改变数据如此重要。 On every change in state - React does a shallow comparison of the updated virtual DOM with the old virtual DOM.在 state 中的每一次更改 - React 都会对更新的虚拟 DOM 与旧的虚拟 DOM 进行浅显比较。 And in this shallow comparison - when it comes across objects - it only checks the address of the object.在这个浅层比较中——当它遇到对象时——它只检查 object 的地址。 So - as long as you have a new address for the parent - the DOM will update correctly.所以——只要你有一个新的父地址——DOM 就会正确更新。

Now, everytime you return from the reducer - as long as you are returning a new object with the updated state - return {... state} or an object with a different address - eg.现在,每次你从减速器返回时——只要你返回一个带有更新的 state 的新 object——返回 {... state} 或一个具有不同地址的 object - 例如。 return initialState - it's perfect. return initialState - 它是完美的。 You don't need to worry about mutations.您无需担心突变。 This is true even if you have a nested object within the state.即使您在 state 中有嵌套的 object,也是如此。 As long as you change the address of the parent - the DOM will update correctly.只要您更改父级的地址 - DOM 就会正确更新。 So feel free to use the code like you did in the first case.因此,请随意使用您在第一种情况下所做的代码。 You don't need to spread over the nested objects.您不需要分布在嵌套对象上。 Your payload will anyway have a different address.无论如何,您的有效负载将具有不同的地址。

The only thing to be weary about is doing something like this:唯一需要担心的是做这样的事情:

    case [actions.editModel]:
        const updatedState = state
        updatedState.model = payload;
        return updatedState;

In this case, the state object gets passed by reference to updatedState - that means both of them will share the same address.在这种情况下,state object 通过引用 updatedState 来传递 - 这意味着它们将共享相同的地址。 And since you're returning updatedState - the address hasn't changed and the DOM won't update correctly/consistently.并且由于您要返回 updatedState - 地址没有更改,并且 DOM 不会正确/一致地更新。

You can simply do this:你可以简单地这样做:

[actions.restoreInitialState]: () => initialState;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM