React batch updates for multiple setState() calls inside useEffect hook
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:
- Inline the component function block synchronously (I think it is equivalent to having an effect running before the other effects and without dependencies)
- In a
useEffect
block synchronously - In a synthetic event handler synchronously (managed by react, such as
onClick={handlerFunction}
)
Non batched calls that will trigger a re-render each time:
- Any asynchronous code (promise/async function in any of the above use cases)
- Non synthetic event (event managed outside react lib)
- That includes XHR or other networks callbacks
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> );
};