在没有Asynch component的情况下离开视图时如何正确清除Redux StateWillUnmount问题

时间:2018-07-26 03:24:18

标签: reactjs redux react-redux

我们已经体验到,由于componentWillUnmount()是异步的,因此当您分派操作以清除componentWillUnmount()内部的某个减速器时,当您直接从该视图转到依赖于减速器这一部分的另一个视图时,可能会导致错误。 。

例如:

假设您具有以下商店状态形状:

const state = {
    list: ["thing"]
}

然后想象一下我在名为Things的视图中使用此状态

然后想象一下,我意识到在其他10个视图中有9个没有使用state.list,所以我决定要防止“膨胀”或“内存泄漏”,因为我的应用程序将扩展为具有多个列表有很多物品因此,我将一个操作清除了状态的这一部分,放入了组件“ WillUnmount in Things”

您希望事件的顺序始终是:

  1. 卸载物品
  2. 调度操作以清除state.list
  3. 然后安装下一个视图
  4. 然后在10个视图中的1个中重新填充state.list(如果在此视图中需要的话)

但是,这不是顺序。有时反而会是:

  1. 卸载事物并直接转到需要state.list的另一个视图
  2. 立即安装下一个视图。我们的视图确实需要state.list,因此我们分派了此操作。或者,因为state.list已经存在,所以我们不调度获取操作,因为我们已经拥有了它,并且有一个条件条件,要求仅在需要时获取它。
  3. 稍后,componentWillUnmount在卸载了所有子项之后终于成功调度了CLEAR操作。
  4. 即使您不想这样做,也无意中清除了该视图中的state.list。当然,由于我们已@connected,所以屏幕变黑了!

也就是说,即使Redux是同步的,componentWillUnmount也不是同步的,因此不能保证在其中调度的任何操作都将按您期望的顺序发生。在任何情况下,如果您确实直接转到确实要该状态部分的另一个视图,这都是一个问题。

一种解决方法是在有条件的componentWillUnmount内部有一个条件,即“由于以下原因,如果我要离开(取消安装)此视图,则仅分派CLEAR操作...不,当我进入该其他视图时确实依赖于本节内容,例如,您可以在localState中拥有一个名为shouldIClearList:之类的属性,并且默认情况下为true,除非我单击名为goToMyOtherViewThatNeedsList的按钮。在许多情况下,如果到另一个需要列表的视图的链接位于一个完全不同的顶级父组件(如Navbar)中,则很复杂,因此,无论您要访问的视图是否是此“问题视图”,您的子事物组件很容易就“知道”了它,而无需一直传递一些道具来通知它本身或使用上下文。

我实际上认为“使用redux导致内存泄漏”的想法是正确的,即使在另一个类似的问题中,丹·阿布拉莫夫本人也认为清除缓存是不必要的Redux: drop part of state as unmounting component?。因此,非常感谢在卸载时清除redux而不遇到类似问题的最佳方法。我能看到的唯一解决方案是永远不要清除componentWillUnmount内部的reducer。太危险了。或者,如果确实需要,则必须确保应用程序中绝对没有办法直接从该视图转到需要此状态部分的另一个视图(在拥有许多团队的大型应用程序中,这是一件非常困难的事情),或者您可以按照前面所述的条件阻止它。有没有最佳实践?

****编辑:本期主题在丹·阿布拉莫夫(Dan Abramov)讨论解决方案的问题上**

github.com/facebook/react/issues/11106

因此,似乎正确的解决方案似乎是完全不使用componentWillUnmount()清除状态,或者(如果必须)始终确保没有两个视图依赖相同的确切树分支。您拥有Things使用的state.list的唯一ID,另一个视图使用的state.list的另一个ID。因此状态可能类似于:

const state = {
    lists: { ThingsList: ["thing"], OtherViewList: null}
}

const state = {
    lists: { ThingsList: null, OtherViewList: ["thing"]}
}

基本上,同一分支上有多个树枝,并且始终使用一个或另一个。到目前为止,这种解决方案是最干净的,并且对我来说最有意义。 **

0 个答案:

没有答案