Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a synchronous alternative of setState() in Reactjs

According to the explaination in the docs:

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

So since setState() is asyncronous and there is no guarantee about its synchronous performance. Is there an alternative of setState() that is syncronous.

For example

//initial value of cnt:0 this.setState({cnt:this.state.cnt+1}) alert(this.state.cnt);    //alert value:0 

Since the alert value is previous value so what is the alternative that will give alert value:1 using setState().

There are few questions on Stackoverflow which is similar to this question but no where I am able to find the correct answer.

like image 484
shubham agrawal Avatar asked Feb 03 '17 06:02

shubham agrawal


People also ask

What to use instead of setState in React?

An alternative to the useState Hook, useReducer helps you manage complex state logic in React applications. When combined with other Hooks like useContext , useReducer can be a good alternative to Redux, Recoil or MobX.

Is setState synchronous in React?

ReactJs sets its state asynchronously because it can result in an expensive operation. Making it synchronous might leave the browser unresponsive. Asynchronous setState calls are batched to provide a better user experience and performance.

Is setState synchronous or asynchronous React?

setState is an Asynchronous Function.

Is useState synchronous or asynchronous?

TL;DR: useState is an asynchronous hook and it doesn't change the state immediately, it has to wait for the component to re-render. useRef is a synchronous hook that updates the state immediately and persists its value through the component's lifecycle, but it doesn't trigger a re-render.


2 Answers

You could wrap setState in a function returning a promise, and then use this function with the await keyword to cause your code to wait until the state has been applied.

Personally, I would never do this in real code, instead I would just put the code I wish to execute after the state update in the setState callback.

Nerveless, here is an example.

class MyComponent extends React.Component {      function setStateSynchronous(stateUpdate) {         return new Promise(resolve => {             this.setState(stateUpdate, () => resolve());         });     }      async function foo() {         // state.count has value of 0         await setStateSynchronous(state => ({count: state.count+1}));         // execution will only resume here once state has been applied         console.log(this.state.count);  // output will be 1     } }  

In the foo function, the await keyword causes the code execution to pause until the promise returned by setStateSynchronous has been resolved, which only happens once the callback passed to setState is called, which only happens when the state has been applied. So execution only reaches the console.log call once the state update has been applied.

docs for async/await:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

like image 38
AbrahamCoding Avatar answered Sep 20 '22 04:09

AbrahamCoding


As you have read from the documentation, there is NO sync alternative, reason as described is performance gains.

However I presume you want to perform an action after you have changed your state, you can achieve this via:

class MyComponent extends React.Component {    constructor(props) {      super(props);      this.state = {       x: 1      };            console.log('initial state', this.state);    }        updateState = () => {     console.log('changing state');      this.setState({        x: 2      },() => { console.log('new state', this.state); })    }        render() {      return (        <div>        <button onClick={this.updateState}>Change state</button>      </div>      );         }  }    ReactDOM.render(    <MyComponent />,    document.getElementById("react")  );
<div id="react"></div>  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
like image 195
Oscar Franco Avatar answered Sep 22 '22 04:09

Oscar Franco