I will try to exlain why it is async and how you can wrap multiple state together,
1) setState
actions are asynchronous and are batched for performance gains. This is explained in the documentation of setState
.
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.
2) Why would they make setState async as JS is a single threaded language and this setState is not a WebAPI or server call?
This is because setState alters the state and causes rerendering. This can be an expensive operation and making it synchronous might leave the browser unresponsive.
Thus the setState calls are asynchronous as well as batched for better UI experience and performance.
A simple example to demonstrate this, is that if you call setState as a reaction to a user action, then the state will probably be updated immediately (although, again, you can't count on it), so the user won't feel any delay, but if you call setState in reaction to an ajax call response or some other event that isn't triggered by the user, then the state might be updated with a slight delay, since the user won't really feel this delay, and it will improve performance by waiting to batch multiple state updates together and re-render the DOM fewer times.
if you have lots of states to update at once, group them all within the same setState
:
this.setState({foo: "one"}, () => {
// do something
this.setState({bar: "two"});
});
So in you above code should be similar to,
async ComponentDidMount() {
const res = await fetch(smth);
this.setState({data: res}, async () => {
//do something more....
const res2 = await fetch(another);
//setState again .....
this.setState({data2: res2});
});
}