score:1
setstate is asynchronous. you can see in this documentation by reactjs
- https://reactjs.org/docs/faq-state.html#why-is-setstate-giving-me-the-wrong-valuejs
- https://reactjs.org/docs/faq-state.html#when-is-setstate-asynchronous
react intentionally “waits” until all components call setstate() in their event handlers before starting to re-render. this boosts performance by avoiding unnecessary re-renders.
however, you might still be wondering why react doesn’t just update this.state immediately without re-rendering.
the reason is this would break the consistency between props and state, causing issues that are very hard to debug.
you can still perform functions if it is dependent on the change of the state value:
option 1: using callback function with setstate
this.setstate({
value: newvalue
},()=>{
// it is an callback function.
// here you can access the update value
console.log(this.state.value)
})
option 2: using componentdidupdate this function will be called whenever the state of that particular class changes.
componentdidupdate(prevprops, prevstate){
//here you can check if value of your desired variable is same or not.
if(this.state.value !== prevstate.value){
// this part will execute if your desired variable updates
}
}
score:2
imagine incrementing a counter in some component:
class somecomponent extends component{
state = {
updatedbydiv: '',
updatedbybtn: '',
counter: 0
}
divcounthandler = () => {
this.setstate({
updatedbydiv: 'div',
counter: this.state.counter + 1
});
console.log('divcounthandler executed');
}
btncounthandler = () => {
this.setstate({
updatedbybtn: 'button',
counter: this.state.counter + 1
});
console.log('btncounthandler executed');
}
...
...
render(){
return (
...
// a parent div
<div onclick={this.divcounthandler}>
// a child button
<button onclick={this.btncounthandler}>increment count</button>
</div>
...
)
}
}
there is a count handler attached to both the parent and the child components. this is done purposely so we can execute the setstate() twice within the same click event bubbling context, but from within 2 different handlers.
as we would imagine, a single click event on the button would now trigger both these handlers since the event bubbles from target to the outermost container during the bubbling phase.
therefore the btncounthandler() executes first, expected to increment the count to 1 and then the divcounthandler() executes, expected to increment the count to 2.
however the count only increments to 1 as you can inspect in react developer tools.
this proves that react
queues all the setstate calls
comes back to this queue after executing the last method in the context(the divcounthandler in this case)
merges all the object mutations happening within multiple setstate calls in the same context(all method calls within a single event phase is same context for e.g.) into one single object mutation syntax (merging makes sense because this is why we can update the state properties independently in setstate() in the first place)
and passes it into one single setstate() to prevent re-rendering due to multiple setstate() calls (this is a very primitive description of batching).
resultant code run by react:
this.setstate({
updatedbydiv: 'div',
updatedbybtn: 'button',
counter: this.state.counter + 1
})
to stop this behaviour, instead of passing objects as arguments to the setstate method, callbacks are passed.
divcounthandler = () => {
this.setstate((prevstate, props) => {
return {
updatedbydiv: 'div',
counter: prevstate.counter + 1
};
});
console.log('divcounthandler executed');
}
btncounthandler = () => {
this.setstate((prevstate, props) => {
return {
updatedbybtn: 'button',
counter: prevstate.counter + 1
};
});
console.log('btncounthandler executed');
}
after the last method finishes execution and when react returns to process the setstate queue, it simply calls the callback for each setstate queued, passing in the previous component state.
this way react ensures that the last callback in the queue gets to update the state that all of its previous counterparts have laid hands on.
score:3
yes, setstate() is asynchronous.
from the link: https://reactjs.org/docs/react-component.html#setstate
- react does not guarantee that the state changes are applied immediately.
- setstate() does not always immediately update the component.
- think of setstate() as a request rather than an immediate command to update the component.
because they think
from the link: https://github.com/facebook/react/issues/11527#issuecomment-360199710
... we agree that setstate() re-rendering synchronously would be inefficient in many cases
asynchronous setstate() makes life very difficult for those getting started and even experienced unfortunately:
- unexpected rendering issues: delayed rendering or no rendering (based on program logic)
- passing parameters is a big deal
among other issues.
below example helped:
// call domytask1 - here we set state
// then after state is updated...
// call to domytask2 to proceed further in program
constructor(props) {
// ..
// this binding is necessary to make `this` work in the callback
this.domytask1 = this.domytask1.bind(this);
this.domytask2 = this.domytask2.bind(this);
}
function domytask1(myparam1) {
// ..
this.setstate(
{
mystate1: 'myvalue1',
mystate2: 'myvalue2'
// ...
},
() => {
this.domytask2(myparam1);
}
);
}
function domytask2(myparam2) {
// ..
}
hope that helps.
score:7
you can use the following wrap to make sync call
this.setstate((state =>{
return{
something
}
})
score:10
good article here https://github.com/vasanthk/react-bits/blob/master/patterns/27.passing-function-to-setstate.md
// assuming this.state.count === 0
this.setstate({count: this.state.count + 1});
this.setstate({count: this.state.count + 1});
this.setstate({count: this.state.count + 1});
// this.state.count === 1, not 3
solution
this.setstate((prevstate, props) => ({
count: prevstate.count + props.increment
}));
or pass callback this.setstate ({.....},callback)
https://medium.com/javascript-scene/setstate-gate-abc10a9b2d82 https://medium.freecodecamp.org/functional-setstate-is-the-future-of-react-374f30401b6b
score:24
i know this question is old, but it has been causing a lot of confusion for many reactjs users for a long time, including me.
recently dan abramov (from the react team) just wrote up a great explanation as to why the nature of setstate
is async:
https://github.com/facebook/react/issues/11527#issuecomment-360199710
setstate
is meant to be asynchronous, and there are a few really good reasons for that in the linked explanation by dan abramov. this doesn't mean it will always be asynchronous - it mainly means that you just can't depend on it being synchronous. reactjs takes into consideration many variables in the scenario that you're changing the state in, to decide when the state
should actually be updated and your component rerendered.
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 rerender the dom fewer times.
score:132
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.
score:184
you can call a function after the state value has updated:
this.setstate({foo: 'bar'}, () => {
// do something here.
});
also, if you have lots of states to update at once, group them all within the same setstate
:
instead of:
this.setstate({foo: "one"}, () => {
this.setstate({bar: "two"});
});
just do this:
this.setstate({
foo: "one",
bar: "two"
});
Source: stackoverflow.com
Related Query
- Why is setState in reactjs Async instead of Sync?
- Why async requests should be made in componentDidMount instead of getInitialState in ReactJS?
- In reactjs is it ok to execute async functions in componentDidMount and do a setstate in the resulting callback?
- Why are consecutive setState calls in async functions not batched?
- Why does setState empty the state object, instead of removing it?
- ReactJs setState updating not in sync with what is being typed in the input box
- reactjs -- Solving setState async problem
- Why does setTimeout return a number instead of text? ReactJS
- Why does setState in this promise take longer to update than the same code as an async function?
- reactjs why use spread operator in setState
- Reactjs why useEffect sometimes runs on every mount/render instead of just first
- onClick a button setState to a value in reactjs instead of undefined
- Why is my async remove method with DELETE restapi call in reactjs not working?
- Why an setState undefined error on a ReactJS Component handleChange method?
- Why do we need middleware for async flow in Redux?
- Why does calling react setState method not mutate the state immediately?
- Reactjs async rendering of components
- Why is console.log() showing react_devtools_backend.js:4049 instead of the file and line number?
- Why calling setState method doesn't mutate the state immediately?
- Why does Async Await work with React setState?
- Why use getDerivedStateFromProps instead of componentDidUpdate?
- React hooks: Why do several useState setters in an async function cause several rerenders?
- ReactJS vs NodeJS - Why do I need to create both?
- How to test useEffect with async function and setState inside
- How do I call setState from another Component in ReactJs
- Material-UI - Why should I use makeStyles instead of inline styles?
- Reactjs setState arrow function syntax
- ReactJS concurrent SetState race condition
- Why do Flux architecture examples use constants for action types instead of strings?
- ReactJS - setState of Object key in Array
More Query from same tag
- Run Redux action only when two other actions were triggered
- How to test reduxForm component using enzyme with snapshots?
- Why is this is undefined when mocking event in React unit testing, using sinon.spy to mock function and enzyme.shallow render for React Component?
- Basic React app is failing to compile - Parsing error
- React component prop throwing error typescript
- React unwanted submit on every character inputed
- Shring text even when using text-overflow: nowrap
- How to recognize env variables in typescript when using vite?
- Prefer inline event handler to avoid indirection in code to improve human readability or use handler function?
- How to deploy web-app created in ReactJS/NodeJS/Express/MongoDB in a local network?
- How to pass extra props to new page through <Link> with React-Router?
- ReactJs always print the same id
- React-virtualized infinite scroll not rendering correctly
- Use Material Design Icons in NPM Electron React project
- Difference between lib and dist folders when packaging library using webpack?
- ./node_modules/mapbox-gl/dist/mapbox-gl.css Module build failed: TypeError: Cannot read property 'toFixed' of undefined
- Pass a variable function to component in React.js
- TypeError: Cannot read property 'handleClick' of undefined
- How to pass parameters in React Function From 1 file to another
- How to convert imperial to metric units?
- Why event.target.value is not updated after running await?
- Get keys of every object and insert that data into array
- 404 error when trying to list envelopes in react sample app
- Add stripe elements multiple publishable keys in ReactJs
- useEffect function is working, but doesn't render on the first click
- MUI v5 passing props to CSS theme using styled()
- Passing props from a parent component to a child component in react
- How can i prefill calendly guests email?
- I want when i got 401 error code then application will logout. But in my case , logout api call but it is not logout properly
- How can I pass a map operation to a component (react datepicker) as a prop?