Why setState in Async Real instead of Sync?

I just found that in the reaction this.setState() function in any component is asynchronous or is called after the function in which it was called is completed.

Now I searched and found this blog ( setState () State mutation operation can be synchronous in ReactJS )

Here he found that setState is asynchronous (called when the stack is empty) or synchronized (called right after the call), depending on how the state change was triggered.

Now these two things are hard to digest.

  1. On a blog, the setState function setState called inside the updateState function, but what called the updateState function is not what the called function should know.
  2. Why do they make setState asynchronous, since JS is a single-threaded language, and this setState is not a WebAPI or server call, so it should only run on a JS thread. Do they do it so that re-rendering does not stop all listeners of events and so on, or is there some other design problem.
+103
javascript multithreading asynchronous reactjs
Mar 18 '16 at 13:30
source share
7 answers

You can call the function after updating the status value:

 this.setState({foo: 'bar'}, () => { // Do something here. }); 

Also, if you need to update several states at once, group them all into the same setState :

Instead:

 this.setState({foo: "one"}, () => { this.setState({bar: "two"}); }); 

Just do it:

 this.setState({ foo: "one", bar: "two" }); 
+135
Nov 03 '16 at 18:39
source share

1) setState actions are asynchronous and are setState to increase performance. This is explained in the setState documentation.

setState () does not immediately modify this.state, but creates a pending state transition. Access to this.state after calling this method can potentially return an existing value. There is no guarantee that setState calls will work synchronously, and calls can be grouped to improve performance.


2) Why do they make setState asynchronous because JS is a single-threaded language, and this setState not a WebAPI or server call?

This is because setState changes state and causes re-rendering. This can be a costly operation, and synchronization can result in the browser not responding.

Thus, setState calls are asynchronous as well as batch to improve user experience and performance.

+78
Mar 18 '16 at 14:38
source share

I know this question is old, but it causes a lot of confusion for many reactionary users for a long time, including me. Recently, Dan Abramov (from the reaction team) simply wrote a wonderful explanation of why the nature of setState asynchronous:

https://github.com/facebook/react/issues/11527#issuecomment-360199710

setState must be asynchronous, and there are several really good reasons for this in Dan Abramov's related explanation. This does not mean that it will always be asynchronous - it basically means that you simply cannot depend on its synchronization . ReactJS takes into account many variables in a scenario in which you change state to decide when state needs to be updated and your component is removed again.
A simple example demonstrating this is that if you call setState as a reaction to a user’s action, then state will probably be updated immediately (although, again, you cannot count on it), so the user won’t feel any delay, but if you call setState in response to an ajax call or some other event that is not triggered by the user, then the state may be updated with a slight delay, since the user will not feel this delay, and this will improve performance, waiting for one there is less lumped batch state update and re-DOM.

+13
Jan 25 '18 at 8:00
source share

Good article here https://github.com/vasanthk/react-bits/blob/master/patterns/27.passing-function-to-setState.md

 // assuming this.state.count === 0 this.setState({count: this.state.count + 1}); this.setState({count: this.state.count + 1}); this.setState({count: this.state.count + 1}); // this.state.count === 1, not 3 Solution this.setState((prevState, props) => ({ count: prevState.count + props.increment })); 

or pass a callback to this.setState({.....},callback)

https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82 https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b

+6
Jan 12 '18 at 10:56
source share

Imagine the increment of the counter in some component:

  class SomeComponent extends Component{ state = { updatedByDiv: '', updatedByBtn: '', counter: 0 } divCountHandler = () => { this.setState({ updatedByDiv: 'Div', counter: this.state.counter + 1 }); console.log('divCountHandler executed'); } btnCountHandler = () => { this.setState({ updatedByBtn: 'Button', counter: this.state.counter + 1 }); console.log('btnCountHandler executed'); } ... ... render(){ return ( ... // a parent div <div onClick={this.divCountHandler}> // a child button <button onClick={this.btnCountHandler}>Increment Count</button> </div> ... ) } } 

There is a counter handler attached to both the parent and child components. This is done intentionally, so we can execute setState () twice in the same click event, but from two different handlers.

As we might suggest, a single click on a button now launches both of these handlers, since the event bubbles from the target to the outermost container during the bubbling phase.

Therefore, btnCountHandler () is started first, expecting it to increment the counter to 1, and then execute the divCountHandler () command to increase the count to 2.

However, the counter only increases to 1, as you can check in React Developer tools.

It proves that react

  • queues for all setState calls

  • returns to this queue after the last method is executed in the context (in this case divCountHandler)

  • combines all mutations of objects that occur in several calls to setState, in the same context (all method calls within the same phase of the event are the same context, for example), into one syntax of the mutation of the object (merging makes sense, because that's why we can update state properties independently in setState () first)

  • and passes it to one setState () to prevent re-rendering due to the many calls to setState () (this is a very primitive description of batch processing).

The resulting code works from a reaction:

 this.setState({ updatedByDiv: 'Div', updatedByBtn: 'Button', counter: this.state.counter + 1 }) 

To stop this behavior, instead of passing objects as arguments to the setState method, callbacks are passed.

  divCountHandler = () => { this.setState((prevState, props) => { return { updatedByDiv: 'Div', counter: prevState.counter + 1 }; }); console.log('divCountHandler executed'); } btnCountHandler = () => { this.setState((prevState, props) => { return { updatedByBtn: 'Button', counter: prevState.counter + 1 }; }); console.log('btnCountHandler executed'); } 

After the last method completes execution and when the reaction returns to process the setState queue, it simply calls a callback for each set set, passing it to the previous state of the component.

This method responds to the fact that the last callback in the queue receives an update of the state that all previous colleagues put into their hands.

+1
Jan 30 '18 at 7:14
source share

You can use the following carry to make a synchronization call

 this.setState((state =>{ return{ something } }) 
0
Jan 20 '19 at 12:00
source share

Yes, setState () is asynchronous.

By link: https://reactjs.org/docs/react-component.html#setstate

  • React does not guarantee that state changes will be applied immediately.
  • setState () does not always immediately update a component.
  • Think of setState () as a request, not as an immediate command to update a component.

Because they think that
From the link: https://github.com/facebook/react/issues/11527#issuecomment-360199710

... we agree that setState () re-rendering synchronously in many cases will be inefficient

Asynchronous setState () makes life very difficult for those who are just starting, and even experiencing, unfortunately:
- unexpected rendering problems: rendering delay or lack of rendering (based on program logic)
- passing parameters is of great importance
among other issues.

Here is an example that helped:

 // call doMyTask1 - here we set state // then after state is updated... // call to doMyTask2 to proceed further in program constructor(props) { // .. // This binding is necessary to make 'this' work in the callback this.doMyTask1 = this.doMyTask1.bind(this); this.doMyTask2 = this.doMyTask2.bind(this); } function doMyTask1(myparam1) { // .. this.setState( { mystate1: 'myvalue1', mystate2: 'myvalue2' // ... }, () => { this.doMyTask2(myparam1); } ); } function doMyTask2(myparam2) { // .. } 

Hope this helps.

0
Aug 11 '19 at 4:22
source share



All Articles