Batching is a React feature that combines all the state updates into a single update, causing a single re-render thereby improving the performance of the app. In earlier versions of React, batching was only done for the event handlers.
Before
Let’s take the following example
On clicking the button, we see the following output in the console
Rerendered
Notice that even though the state updates twice,
once for counter1
and once for counter2
,
the app is re-rendered only once.
But in the case of asynchronous state updates, state updates are not batched, as seen in the following example.
Clicking the button gives the following output in the console.
Rerendered
Rerendered
Each state update causes a re-render.
It is because until React 18, React only batched updates in React event handlers. Updates inside promises, setTimeout, native event handlers or any other event were not batched in React by default.
After
Starting in React 18 with createRoot, all updates will be automatically batched, no matter where they originate from.
Runinng the above code with React 18 by upgrading to createRoot gives the console output as below
Rerendered
The old behaviour is still maintained when using React 18 with ReactDom.render
Automatic batching impact on Classes and Hooks
It was possible to synchronously read state updates inside of events in class components.
This is because React mutated this.state
to point to the updated state
in the middle of our function.
This is not the case in hooks as there is no this
to mutate.
With the createRoot
changes in React 18,
it is not possible to get an updated state in between the calls to setState
.
Let’s modify the above example using the class component as below -
We can see from the above example that we get the updated state
{ counter1: 1, counter2: 0 }
before React 18,
whereas with React 18,
the state remains the same { counter1: 0, counter2: 0 }
.
For some cases where we want to read something from the DOM immediately after a state change,
we can opt-out of batching with ReactDOM.flushSync()
as seen below.
It gives the below output
Rerendered
Rerendered
Note:
The unstable_batchedUpdates
API is used by some React libraries to force
setState
to be batched outside of event handlers.
This API is still present in React 18 to ease migration. However, it is redundant due to automatic batching and will be removed in future versions.
To know more about automatic batching, check out the WG discussion.