Source:  Twitter logo

I made my componentWillMount() async. Now I can using await with the setState.

Here is the sample code:

componentWillMount = async() => {
  const { fetchRooms } = this.props
  await this.setState({ })
  fetchRooms()
}

So question here is this.setState returns promise because I can use await with it?

Edit

When I put await then it runs in a sequence 1, 2, 3 And when I remove await then it runs 1, 3, 2??

  componentWillMount = async() => {
    const { fetchRooms } = this.props
    console.log(1)
    await this.setState({ } => {
      console.log(2)
    })
    console.log(3)
    fetchRooms()
  }

You can promisify this.setState so that you can use the React API as a promise. This is how I got it to work:

class LyricsGrid extends Component {

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

Later, I call this.setAsyncState using the standard Promise API:

this.setAsyncState({ lyricsCorpus, matrix, count })
  .then(foo1)
  .then(foo2)
  .catch(err => console.error(err))
24 users liked answer #0dislike answer #024
alki profile pic
alki

setState is usually not used with promises because there's rarely such need. If the method that is called after state update (fetchRooms) relies on updated state (roomId), it could access it in another way, e.g. as a parameter.

setState uses callbacks and doesn't return a promise. Since this is rarely needed, creating a promise that is not used would result in overhead.

In order to return a promise, setState can be promisified, as suggested in this answer.

Posted code works with await because it's a hack. await ... is syntactic sugar for Promise.resolve(...).then(...). await produces one-tick delay that allows to evaluate next line after state update was completed, this allows to evaluate the code in intended order. This is same as:

this.setState({ roomId: room && room.roomId ? room.roomId : 0 }, () => {
  console.log(2)
})

setTimeout(() => {
  console.log(3)
});

There's no guarantee that the order will stay same under different conditions. Also, first setState callback isn't a proper place to check whether a state was updated, this is what second callback is for.

19 users liked answer #1dislike answer #119
Estus Flask profile pic
Estus Flask

setState does not return a promise.

setState has a callback.

this.setState({
    ...this.state,
    key: value,
}, () => {
    //finished
});
15 users liked answer #2dislike answer #215
Tazo leladze profile pic
Tazo leladze

It does not return a promise.

You can slap the await keyword in front of any expression. It has no effect if that expression doesn't evaluate to a promise.

setState accepts a callback.

3 users liked answer #3dislike answer #33
Quentin profile pic
Quentin

Don't think setState is returning a Promise but you can always do this

 await new Promise( ( resolve ) => 
     this.setState( {
         data:null,
     }, resolve )
 )

or you can make some utility function like this

const setStateAsync = ( obj, state ) => {
    return new Promise( ( resolve ) =>
        obj.setState( state , resolve )
    )
}

and use it inside a React.Component like this:

await setStateAsync(this,{some:'any'})
3 users liked answer #4dislike answer #43
Bogdan Manole profile pic
Bogdan Manole

You can simple customize a Promise for setState

  componentWillMount = async () => {
    console.log(1);
    await this.setRooms();
    console.log(3);
  };

  setRooms = () => {
    const { fetchRooms } = this.props;
    return fetchRooms().then(({ room }) => {
      this.setState({ roomId: room && room.roomId ? room.roomId : 0 }, _ =>
        console.log(2)
      );
    });
  };

Or

  setRooms = async () => {
    const { fetchRooms } = this.props;
    const { room } = await fetchRooms();

    return new Promise(resolve => {
      this.setState({ roomId: room && room.roomId ? room.roomId : 0 }, _ =>
        resolve()
      );
    });
  };

Hope this help =D

2 users liked answer #5dislike answer #52
mvofreire profile pic
mvofreire

Simpler way to answer this question is we can use promisify function present in pre-installed util library of node.js and then use it with the await keyword.

import {promisify} from 'util';

updateState = promisify(this.setState);
await this.updateState({ image: data });
0 users liked answer #6dislike answer #60
siraj pathan profile pic
siraj pathan

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).