父母删除的子组件仍会获得商店更改事件

时间:2015-11-18 21:10:46

标签: reactjs flux reactjs-flux

tl; dr:mridgway在这里描述的同一问题:isMounted is not enough to know if you can setState

我有一个像这样的组件层次结构:

PhasesList
- Phase
  - PhaseHeader
- Phase
  - PhaseHeader

还有一个PhaseStore,它维护一个阶段列表及其详细信息。

在所有三个组件中,我监听PhaseStore更改并根据更改更新状态(重新呈现)。例如,如果用户在PhaseHeader中更改阶段名称,则会触发操作,存储更新并发出更改事件。该更改事件将传播到PhaseList,Phase和PhaseHeader,并使用实际名称值进行呈现。

有一个问题,我可以删除一个阶段。此操作在PhaseStore中处理,其中相位从列表中删除并发出更改事件(如在其他情况下)。此事件由所有组件处理,从上到下(因为所有组件都会监​​听商店更改)。

因此,在PhasesList中,渲染了一组新的阶段,而没有删除。但是,删除的阶段组件仍然会收到更改事件,而PhaseHeader也会这样做。

在这两个组件中,在相变处理程序中我使用setState。我得到的信息是:

  

警告:setState(...):只能更新已安装或安装的组件。这通常意味着您在已卸载的组件上调用了setState()。这是一个无操作。

我发现人们使用isMounted来检查该组件是否仍在DOM中。此方法现已弃用。

我怎样才能以适当的方式解决这个问题?我的组件设计及其相互通信的问题是什么?

2 个答案:

答案 0 :(得分:5)

通常,您应该使用生成容器组件的React Redux。它已经过大量优化,使用setState()比手动代码更快,并且特别为您提到的案例提供保护。

否则你可以这样做:

componentDidMount() {
  this.unsubscribe = store.subscribe(this.handleChange.bind(this));
}

componentWillUnmount() {
  this.unsubscribe();
  this.unsubscribe = null;
}

handleChange() {
  if (!this.unsubscribe) {
    return;
  }

  this.setState(/* ... */);
}

答案 1 :(得分:2)

非常自然的方式是订阅componentDidMount中的活动并取消订阅componentWillUnmount

另一件事是,我不是在各个组件级别上听取更改,而是在根组件级别更好地执行此操作,在您的情况下,PhasesList。它将通过道具传递所有更改,允许React确定哪个孩子需要更新。