如果您执行异步操作以更新componentWillMount
中的状态(如文档所述),但在异步调用完成之前卸载了组件(用户导航),则最终会出现异步回调尝试在现在卸载的组件上设置状态,以及
"不变违规:replaceState(...):只能更新已安装或 安装组件。"
错误。
最好的解决方法是什么?
感谢。
答案 0 :(得分:9)
在替换状态之前,您可以使用component.isMounted
方法检查组件是否实际附加到DOM。 Docs
如果组件被渲染到DOM中,
isMounted()
将返回true
, 否则false
。您可以使用此方法来保护异步调用 到setState()
或forceUpdate()
。
UPD:在您投票之前。这个答案是在2年前给出的。这是当天回归的方式。如果您刚刚开始使用React,请不要按照此答案。使用componentDidMount
或您需要的任何其他生命周期钩子。
答案 1 :(得分:3)
isMounted()
实际上是解决大多数问题的简单方法,但是,我不认为这是解决并发问题的理想解决方案。
现在想象一下,用户可以非常快速地点击许多按钮,或者他的移动连接非常差。 最终可能会发生2个并发请求,并且在完成时将更新状态。
如果您触发请求1然后请求2,那么您可能希望将请求2的结果添加到您的州。
现在想象由于某种原因请求2在请求1之前结束,这可能会使您的应用程序不一致,因为它将显示request2结果然后请求1,而您的最后一次"兴趣"实际上是在请求1回答。
要解决此类问题,您应该使用某种Compare And Swap算法。基本上,这意味着在发出请求之前,您将一些对象节点置于状态,并且在请求完成时,如果要交换的节点仍然是您在请求完成时感兴趣的节点,则与引用相等进行比较。
这样的事情:
var self = this;
var resultNode = {};
this.setState({result: resultNode});
this.getResult().then(function(someResult) {
if ( self.state.result === resultNode ) {
self.setState({result: someResult})
}
}):
有了类似的东西,如果用户点击快速导致同一组件内的当前请求的按钮,就不会出现并发问题。
答案 2 :(得分:2)
更新2016
不要开始使用isMounted
,因为它会从React see the docs中删除。
来自cmomponentWillMount
的异步调用引起的问题的最佳解决方案可能是将事情移至componentDidMount
。
有关如何正确解决此问题以及 not 需要如何使用isMounted的更多信息:isMounted is an Antipattern