Set ReactJS state asynchronously

If you perform an asynchronous action that updates the state in componentWillMount (as the documents say), but the component is unmounted (the user enters standby mode) before this asynchronous call is completed, you will receive an async callback attempt to set the state on the now disabled component and

"Invariant violation: replaceState (...): can only update a mounted or mounting component."

error.

What is the best way?

Thanks.

+6
source share
3 answers

update 2016

Do not start using isMounted , because it will be removed from React, see documents .

Probably the best solution to problems arising from an asynchronous call from cmomponentWillMount is to move objects to componentDidMount .

Read more about how to get around this problem and how not to use isMounted here: isMounted is Antipattern

+2
source

You can use the component.isMounted method to check if the component was really bound to the DOM before replacing its state. Docs .

isMounted() returns true if the component is mapped to the DOM, false otherwise. This method can be used to protect asynchronous calls to setState() or forceUpdate() .

UPD: before doing downvote. This answer was given 2 years ago. And that was the way to do something in those days. If you are just starting to use React, do not follow this answer. Use componentDidMount or any other life cycle you need.

+9
source

isMounted() is actually an easy way to solve most problems, however I don't think this is the perfect solution for concurrency problems.

Now imagine that the user clicks a lot on many buttons, or maybe he has a very poor mobile connection. It may happen that, finally, 2 simultaneous requests are pending, and upon completion it will update the state.

If you run query 1 and then query 2, you expect the result of query 2 to be added to your state.

Now imagine that for some reason, query 2 ends before query 1, this will probably make your application inconsistent, because it will display the results of query2, and then request 1, while your last β€œinterest” was actually in the query 1 answer.

To solve this problem, it is better to use some Compare and Swap algorithm. This basically means that before issuing the request, you put some node object in the state and upon completion of the request, you compare with reference equality if the node for swaping will still be the node that interests you when the request is completed.

Something like that:

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

With something similar, you will not have a problem with concurrency if the user clicks on the buttons leading to the current requests inside the same component.

+3
source

Source: https://habr.com/ru/post/973192/


All Articles