Does this.setState return promise in react
Solution 1
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.
Solution 2
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))
Solution 3
setState does not return a promise.
setState has a callback.
this.setState({
...this.state,
key: value,
}, () => {
//finished
});
Solution 4
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.
Solution 5
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'})
Related videos on Youtube
Profer
Updated on July 09, 2022Comments
-
Profer almost 2 years
I made my
componentWillMount()
async. Now I can usingawait
with thesetState
.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 useawait
with it?Edit
When I put await then it runs in a sequence
1, 2, 3
And when I remove await then it runs1, 3, 2
??componentWillMount = async() => { const { fetchRooms } = this.props console.log(1) await this.setState({ } => { console.log(2) }) console.log(3) fetchRooms() }
-
Tholle over 5 years
setState
does not return a promise, but your code should work fine withoutawait
before it. What is it that you want to achieve? You can also make thecomponentWillMount
method async instead of creating a property for every instance.async componentWillMount() { ... }
-
Estus Flask over 5 yearsPossible duplicate of stackoverflow.com/questions/53080701/…
-
-
Profer over 5 yearsNo I can see the change. Let me clear you the question again. when I put the
await
in front ofthis.setState
it stops the code. I checked it by putting logs one before and afterthis.setState
. And that's why I have asked question here. -
Qwerty about 5 yearsYou don't have to bind arrow function methods so you don't even need to write constructor by hand. They capture the this of surrounding context automatically.
-
SeanMC about 5 yearsthey don't have an inner-this, so it just uses the outer this
-
Xmanoux over 4 yearsIn my opinion the main need of a promise with setState is a subjective thing : the .then syntax is very elegant and easy to understand. (more than a second callable post updating argument)
-
Estus Flask over 4 years@Xmanoux It looks neat but one-tick delay can interfere with React lifecycle if it's unintentional. A lot of things can happen during 1 tick. More specifically, the component could be unmounted (this will happen in the OP because componentWillMount shouldn't be async). There's a known problem with promise control flow in general because promises are not cancellable and aren't aware of component lifecycle. It just becomes more prominent if promises are used in places where they aren't necessary.
-
Hasan Sefa Ozalp over 3 yearsIf you use hooks, there is no callback for setState.
-
Leri Gogsadze over 3 years@HasanSefaOzalp But you can use
effect
for that. -
Danish over 2 yearsWarning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().
-
Danish over 2 yearsWarning: State updates from the useState() and useReducer() Hooks don't support the second callback argument. To execute a side effect after rendering, declare it in the component body with useEffect().
-
Tazo leladze over 2 years@Danish my answer was about classed based component not for hooks.