24

my function looks like this:

this.setState(prevState => ({
 time : prevState.time + 1
}), function() {
 doSomethingWithNewState(this.state.time)
})

is it correct to use await in this situation? like this:

await this.setState(prevState => ({
 time : prevState.time + 1
}));
doSomethingWithNewState(this.state.time);
lalezky
  • 374
  • 1
  • 3
  • 11
  • 2
    No. It's not right way to use await in front of `setstate` function. If you want do async operation, don it in separate thread and using the callback function update the `setstate` function. – kumar k Aug 22 '18 at 14:11
  • https://stackoverflow.com/questions/47019199/why-does-async-await-work-with-react-setstate – anshu purohit Aug 22 '18 at 14:11

6 Answers6

31

You can't await this.setState for the reasons already stated. But you can write your own awaitable setState function easily:

promisedSetState = (newState) => new Promise(resolve => this.setState(newState, resolve));

now you can call

await promisedSetState({ someState: true });
David Schumann
  • 13,380
  • 9
  • 75
  • 96
  • 1
    Is it possible to do this with hooks? It would nice if someone could edit the answer. The new version of setState in hooks expects only 1 argument. – josealvarez97 Feb 10 '23 at 19:18
  • 1
    @josealvarez97 it's not necessary to await as you can just add a `useEffect` hook to react to state changes where the state variable is the hook dependency. Also if you think you must await for state change, then maybe you're doing something wrong. The thought paradigm of using hooks is completely different from the class lifecycle paradigm. – ADTC Mar 10 '23 at 13:49
23

No this.setState doesn't return a promise.

So you can't use await in this case. You need to use the callback.

Anas
  • 5,622
  • 5
  • 39
  • 71
  • 1
    according to MDN, await expression can be used for "a Promise or any value to wait for. " https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await – J.Ko Dec 14 '18 at 18:13
  • 2
    await doesn't work with a callback. You can test it. – Anas Dec 14 '18 at 19:07
  • 2
    @Anas await is working fine please check here https://next.plnkr.co/edit/0FqhaCGmtV0xkgAx?open=Hello.js&deferRun=1 – Dhaval Patel Feb 19 '19 at 06:24
4

As the previous answer mentioned, setState() does not return a Promise, so you cannot use it with await as you intend. (Although you can await synchronous code as well).

When it's said that setState() is asynchronous, what's meant is that the effect of setState() may happen at a later time.

Furthermore, while reading this.state in the callback function will give you the state of the component at that particular moment in time when the callback gets executed, it's not exactly what you'd expect, because all callback functions are called after a batch of setState() calls gets executed. (See this issue).

Dan
  • 9,912
  • 18
  • 49
  • 70
  • according to MDN, await expression can be used for "a Promise or any value to wait for. " https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await – J.Ko Dec 14 '18 at 19:13
  • 1
    Yep, that's what I meant in the first sentence of my answer :-) – Dan Dec 21 '18 at 13:20
2

Definitely not. You can pass a callback to the setState like this:

this.setState(prevState => ({
 time : prevState.time + 1
}), 
() => doSomethingWithNewState(this.state.time));
S. Hesam
  • 5,266
  • 3
  • 37
  • 59
0

As David says, that promisedSetState function works great.

One thing to keep in mind, if you are destructuring your state in your function, do not use the destructured state as it is a const and won't change.

myFunction = () => {
const { someState } = this.state;
await promisedSetState({someState: someValue });
console.log(someState) <<<--- will be old value
console.log(this.state.someState) <<<--- will be new value
}
Alex S
  • 51
  • 3
-2

setState takes a callback? Not sure why the first example would be an issue

https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296

stackoverfloweth
  • 6,669
  • 5
  • 38
  • 69