On this answer by Dan Abramov here on SO, I've found out the following:
Does React keep the order for state updates?
Currently (React 16 and earlier), only updates inside React event handlers are batched by default. There is an unstable API to force batching outside of event handlers for rare cases when you need it.
He also mentions that in this Github issue:
https://github.com/facebook/react/issues/10231#issuecomment-316644950
In current release, they will be batched together if you are inside a React event handler. React batches all setStates done during a React event handler, and applies them just before exiting its own browser event handler.
But the fact is that this snippet seems to prove that updates for multiple setState
calls inside a useEffect()
are batched.
QUESTION
Does React also always batch updates for multiple setState()
calls inside useEffect
? Where else does it do that ?
NOTE: According to his answers, on next major release (probably v17) React will batch everywhere by default.
SNIPPET: batch updates inside a useEffect()
with multiple setState()
calls
function App() {
console.log('Rendering app...');
const [myState,setMyState] = React.useState(0);
const [booleanState, setBooleanState] = React.useState(false);
console.log('myState: ' + myState);
console.log('booleanState: ' + booleanState);
React.useEffect(()=>{
console.log('Inside useEffect...');
setMyState(1);
setMyState((prevState) => prevState +1);
setMyState(3);
setMyState(4);
setMyState(5);
setBooleanState(true);
},[]);
return(
<div>App - Check out my console!</div>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
React may batch multiple setState() calls into a single update for performance.
React may batch multiple setState calls into a single update for performance. Because props and state may be updated asynchronously, you should not rely on their values for calculating the next state.
By following this rule, you ensure that Hooks are called in the same order each time a component renders. That's what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls. (If you're curious, we'll explain this in depth below.)
React uses batching to group state updates within event handlers and inbuilt hooks. It prevents components from re-rendering for each state update and improves application performance. React 17, and prior versions only support batching for browser events.
Nice question. Here is additional info to complete @FranklinOcean answer.
2021 update: upcoming changes in React 18
Please see Dan Abramov update concerning this topic in React 18, which is the one that adds automatic batching: https://github.com/reactwg/react-18/discussions/21
Answer for current version of react, which is 17.0.2, and below, as of 2021.
Based on the following codesandbox:
Batched setStuff
calls:
useEffect
block synchronouslyonClick={handlerFunction}
)Non batched calls that will trigger a re-render each time:
I'll try re-run the sandbox with future versions of react to see how it goes!
If state updates happen directly, React will batch your updates.
Batched:
export default () => {
const [a, setA] = React.useState(0);
const [b, setB] = React.useState(0);
useEffect(() => {
setA(1); setB(1);
},[]);
return (
<div>
<p>A: {a}</p>
<p>B: {b}</p>
</div> );
};
Clicking this button will re-render the component only once.
Non-Batched:
export default () => {
const [a, setA] = React.useState(0);
const [b, setB] = React.useState(0);
useEffect(() => {
setTimeout(() => { setA(1); setB(1); }, 1000); }
, []);
return (
<div>
<p>A: {a}</p>
<p>B: {b}</p>
</div> );
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With