异步设置ReactJS状态

Set ReactJS state asynchronously

本文关键字:状态 ReactJS 设置 异步      更新时间:2023-09-26

如果你做了一个异步操作来更新componentWillMount中的状态(就像文档说的那样),但是在异步调用完成之前组件被卸载了(用户导航离开了),你最终会得到异步回调,试图在一个现在被卸载的组件上设置状态,并且

"不变量违反:replaceState(…):只能更新一个挂载的或安装组件。"

错误。

解决这个问题的最好方法是什么?

谢谢。

您可以使用component.isMounted方法来检查组件是否实际上附加到DOM之前,替换它的状态。Docs .

isMounted()返回true如果组件被渲染到DOM,否则false。您可以使用此方法来保护异步调用setState()forceUpdate() .

UPD:在你投反对票之前。这个答案是两年前给出的。那是当时的一种做事方式。如果你刚刚开始使用React,不要遵循这个答案。使用componentDidMount或者其他你需要的生命周期钩子

isMounted()实际上是解决大多数问题的简单方法,然而,我不认为这是并发问题的理想解决方案。

现在想象一下,用户非常快速地点击了许多按钮,或者他的移动连接非常差。可能最后有2个并发请求处于挂起状态,并且在完成时将更新状态。

如果您触发请求1,然后触发请求2,那么您将期望请求2的结果被添加到您的状态。

现在想象一下,由于某种原因,请求2在请求1之前结束,这可能会使你的应用程序不一致,因为它将显示请求2的结果,然后是请求1,而你最后的"兴趣"实际上是在请求1的答案。

要解决这种问题,您应该使用某种比较和交换算法。基本上,这意味着在发出请求之前,您将一些对象节点置于状态,并且在请求完成时,如果要交换的节点在请求完成时仍然是您感兴趣的节点,则与引用相等进行比较。

像这样:

var self = this;
var resultNode = {};
this.setState({result: resultNode});
this.getResult().then(function(someResult) {
    if ( self.state.result === resultNode ) {
        self.setState({result: someResult})
    }
}):

有了这样的东西,您就不会有并发问题,以防用户快速单击按钮导致同一组件内的当前请求。

更新2016

不要开始使用isMounted,因为它将从React中删除,参见文档。

对于cmomponentWillMount异步调用产生的问题,最好的解决方案可能是将内容移到componentDidMount

关于如何正确解决这个问题以及如何需要使用isMounted的更多信息: