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中。此方法现已弃用。
我怎样才能以适当的方式解决这个问题?我的组件设计及其相互通信的问题是什么?
答案 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确定哪个孩子需要更新。