gpt4 book ai didi

angular - 进行深度复制还是不进行深度复制-无论如何,为什么ngrx的状态应该是不可变的?

转载 作者:行者123 更新时间:2023-12-03 09:42:05 24 4
gpt4 key购买 nike

我是ngrx的新手(并且从未使用过redux),并且正在尝试理解所有内容-尤其是您是否需要状态的深拷贝。这是到目前为止我学到的东西,仍然让我感到困惑(进一步以粗体显示)。

Ngrx文档state

Each reducer function takes the latest Action dispatched, the current state, and determines whether to return a newly modified state or the original state.



他们还指出 state transitions need to happen immutably-如果您更改状态,则需要在副本上:

Each action handles the state transition immutably. This means that the state transitions are not modifying the original state, but are returning a new state object using the spread operator.



他们没有说为什么这是必要的,除了促进了引用完整性之外(而且我不太确定如何确保您的引用指向数据-我只从关系数据库上下文中知道该术语-发挥了全部作用):

The spread syntax copies the properties from the current state into the object, creating a new reference. This ensures that a new state is produced with each change, preserving the purity of the change. This also promotes referential integrity, guaranteeing that the old reference was discarded when a state change occurred.



但是,(引用完整性和上面的部分)并没有真正解释为什么这样做是必要的。
Elsewhere on SO,我发现一条评论表明它允许将Angular的更改检测策略更改为 OnPush

(如果一个 Action 可以触发多个reducer,如何合并最终的状态副本,我也有些困惑,但这显然是由状态的 each reducer exclusively looking after a separate slice和redux意识到这一点来解释的。)

不过,重要的事情似乎是状态 creates a new reference的副本(浅或深),这意味着ngrx正在向其订户推送更改:

If the returned object reference has changed, it will trigger any related RxJS state subscriptions for the particular piece of state in question. Which subscriptions are triggered can be minimised using some good ngrx selectors.



一般来说, Redux FAQ列出了为什么不变性是一件好事,还有 why redux requires it:
提高性能,简化调试,简化推理,更安全地处理数据,进行浅层相等性检查

他们也说

enables sophisticated change detection techniques to be implemented simply and cheaply, ensuring the computationally expensive process of updating the DOM occurs only when it absolutely has to



正如刚刚指出的(作为不可变性的要求之一), redux进行了浅层相等性检查

Nrgx的文档,但是,recommend deep cloning (再加上,我认为如果副本引用了旧对象,状态并不是真正不变的):

Note: The spread operator only does shallow copying and does not handle deeply nested objects. You need to copy each level in the object to ensure immutability. There are libraries that handle deep copying including lodash and immer.



但是,深拷贝可能具有 "nasty" side effects(例如,在Angular组件中使用克隆的项时):

This question even extends to the way Angular's ngFor change detection works (and using a trackBy function complicates that even further!): when I clone every item in Thing[] and have my reducer return a new list of cloned Things, Angular will think it's a brand new list (which it technically is) and run change-detection for all items in the list: They will also be brand new, and as such, old list items get removed and new ones get added to the DOM.

Suppose you have a ThingComponent for each Thing in the ngFor list. In that component, ngOnChanges will fire. But here's the thing: the SimpleChanges passed to ngOnChanges will never contain previousValues, because the whole list got replaced, and so there is previous value: everything is brand new, from Angulars perspective.



作者还指出了一种解决方案( trackBy),但是我现在想知道:
在ngrx 中使用深层复制确实是一个好主意(如果要使库工作所需的全部只是对根/状态对象的新对象引用,您是否真的需要深层复制)?最后一个引号听起来似乎是一个更好的主意,那就是只交换根对象,即状态,输出,以获得一个新的引用,然后触发订阅,但将嵌套的对象(尤其是列表)保留下来。

最佳答案

  • 深度复制

  • 我们的目标是使我们的应用程序尽可能快地运行,这意味着在不需要或多余时减少计算量。

    Angular在onPush和Default上有2种变化检测策略,第一个检查传递给输入的变量的指针,第二个进行深度检查,对重对象非常繁琐。但是它们只有一件事-仅在更改数据后才重新渲染。

    深度复制是不好的,因为它会使相同的数据在新的对象指针下呈现,这会导致呈现周期,并且由于数据是相同的,因此重新呈现的结果也将相同,除非它是与时间相关的应用程序。

  • 不变状态

  • 数据流的最佳方法是从上到下,并且bottom可以通知top更改数据。

    在这种情况下,我们总是可以通过检查 parent 以及他们对数据的处理情况来找到数据是如何到达这里的,而且我们可以单方面了解数据的变化情况,并且可以找到导致变化的原因。

    如果我们在需要更改的地方更改数据而不是通知顶部,那么随着时间的流逝,我们将不再容易找到谁来做,因为这些地方在代码中无处不在,我们需要检查所有地方以查找问题。

    关于angular - 进行深度复制还是不进行深度复制-无论如何,为什么ngrx的状态应该是不可变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59577923/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com