简体   繁体   English

什么时候应该在Redux reducer中深度克隆状态的什么部分?

[英]When and what part of the state is supposed to be deep cloned in Redux reducer?

I have been writing my reducers like this for a long time: 我很长时间以来一直在写我的减速器:

const init = {
  a: 'b'
}

const reducerName = function (state = init, action) {
  let newState = _.cloneDeep(state) // using lodash
  case 'ACTION_NAME':
    newState.a = 'c'
    return newState
  default:
    return state
}

One day I realised, that this is probably a very stupid way of doing it, since I am creating a new object in every reducer every time when action is triggered, even if the state would not change at all. 有一天,我意识到这可能是一种非常愚蠢的方法,因为每次动作触发时我都会在每个reducer中创建一个新对象,即使状态根本不会改变。

So, my colleague passed me tweet of Dan Abramov, where he says there is no need to deep clone the state. 因此,我的同事给我发了Dan Abramov的推文,他说没有必要深入克隆该州。 And this got me thinking, when and how to actually do the deep cloning. 这让我开始思考,何时以及如何进行深度克隆。

Let's say I have this kind of state in reducer: 假设我在reducer中有这种状态:

const init = {
  very: {
    deeply: {
      nested: 'string'
    }
  }
  notSoDeeplyNested: 'string'
}

So which one of the following would be the right way/closest to the right way to do manage the state: 因此,以下哪一项是管理状态的正确方法/最接近正确的方法:

1) 1)

const reducerName = function (state = init, action) {
  case 'ACTION_NAME':
    let newState = Object.assign({}, state) // Make a shallow copy
    newState.very.deeply = action.deeply
    return newState
  default:
    return state
}

2) 2)

const reducerName = function (state = init, action) {
  case 'ACTION_NAME':
    let newVery = _.cloneDeep(state.very)
    let newState = Object.assign({}, state, very)
    newState.very.deeply = action.deeply
    return newState
  default:
    return state
}

3) 3)

const reducerName = function (state = init, action) {
  case 'ACTION_NAME':
    let newDeeply = _.cloneDeep(state.very.deeply)
    let newState = Object.assign({}, state, { very: { deeply: newDeeply } ) // Cloning only the nested part, which actually changes?
    newState.very.deeply = action.deeply
    return newState
  default:
    return state
}

The last one doesn't seem proper even for me, but I have hard time wrapping my head around this. 最后一个甚至对我来说似乎都不合适,但是我很难解决这个问题。

So, as far as I understand at least a shallow copy has to be done everytime, but when am I supposed to deep clone something and which part of the object it would be? 因此,据我所知,至少每次都必须进行浅表复制,但是我应该何时深度复制某些对象以及对象的哪一部分呢? And by which part I mean would it be the first level object or only the nested part? 我指的是哪一部分是第一级对象还是仅是嵌套部分?

To answer your question: No, you don't deep-clone. 要回答您的问题:不,您不进行深度克隆。 Instead, you selectively shallow-copy parts that need changing. 相反,您可以选择浅化复制需要更改的零件。 You can use destructuring to only target paths with changes while keeping existing references to unchanged parts. 您可以使用解构将目标仅更改为目标,同时保留对未更改零件的现有引用。

In the following example, it shallow-copies init to a object but replaces very with a new object. 在下面的示例中,它将init浅层复制到一个对象,但very用新对象替换。 The same goes for the very object. 这同样适用于在very对象。 It shallow-copies everything from init.very but replaces deeply with the new value. 它从init.very浅表复制了所有内容,但是用新值deeply替换了它。

case 'ACTION_NAME':
  return {
    ...init,
    very: {
      ...init.very,
      deeply: action.deeply
    }
  };

It translates to this in ES5: 在ES5中将其翻译为:

case 'ACTION_NAME':
  return Object.assign({}, init,
    {very: Object.assign({}, init.very,
      {deeply: action.deeply})});

In the end, you have a new state object that is comprised partly of existing values and references, and partly of changed values, similar to that of persistent data structures. 最后,您将拥有一个新的状态对象,该对象部分由现有值和引用组成,部分由更改后的值组成,类似于持久性数据结构。 We changed the objects leading to the changed data, but not everything to the point that it can be called a deep clone. 我们更改了导致更改后的数据的对象,但并非将所有内容更改为可以称为深度克隆的内容。

It can get verbose for deep structures, but Redux advocates shallow objects instead of deeply nested ones. 对于深层结构,它可能很冗长,但是Redux提倡浅层对象,而不是深层嵌套的对象

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

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