Skip to main content

What is batching in React?

What batching is

Batching is a mechanism where React combines several setState calls into one shared render, so the component re-renders only once, instead of after every state change.


Example without batching (in theory)

javascript
function Counter() { const [count, setCount] = useState(0); const handleClick = () => { setCount(count + 1); setCount(count + 1); setCount(count + 1); }; console.log('render', count); return <button onClick={handleClick}>{count}</button>; }

If batching did not exist, React would do:

javascript
setState 1 → render setState 2 → render setState 3 → render

That would mean three re-renders in a row, slow and inefficient.


With batching (how React actually works)

React groups all these updates into one batch:

javascript
setState 1 setState 2 setState 3 1 shared render

So the component re-renders only once.


What happens under the hood

React does not update state immediately when setState is called. It:

  1. Puts the update into an update queue;
  2. Waits until all synchronous events finish processing (for example, onClick);
  3. Then applies all accumulated updates in one batch, recomputes state, and triggers one render.

Example (a visible result)

javascript
function Counter() { const [count, setCount] = useState(0); const handleClick = () => { setCount(c => c + 1); setCount(c => c + 1); setCount(c => c + 1); }; console.log('render'); return <button onClick={handleClick}>{count}</button>; }

After one click:

  • All three setCount calls run;
  • count increases by 3;
  • The component re-renders once.

When batching works

With React 18, always, by default (previously it only worked inside React events, and now it works in any asynchronous context too).

Example - React 17 (the old behavior):

javascript
useEffect(() => { setCount(c => c + 1); setFlag(true); });

React 17: performs two separate renders, because the updates happen asynchronously (inside useEffect).

React 18: batching is enabled even for async code (fetch, setTimeout, Promise).


Example (React 18 - automatic batching)

javascript
setTimeout(() => { setCount(c => c + 1); setFlag(f => !f); }, 1000);

React 17: → two renders (batching did not work outside React events). React 18: → one render (both operations are grouped automatically).


Batching can be disabled manually (rarely)

Sometimes you need to update the UI immediately (for example, in tests or animations). There is flushSync for this:

javascript
import { flushSync } from 'react-dom'; flushSync(() => setCount(c => c + 1)); flushSync(() => setFlag(true));

Each operation runs as a separate render, React will not group them.


Why batching matters

BenefitWhat it gives
Fewer re-rendersReact does not update the component after every little thing
More predictable behaviorAll updates are applied "atomically"
PerformanceLess diffing, reconciliation, and DOM work
ConsistencyState is recomputed from current data

How batching relates to concurrent rendering (React 18)

  • React can now defer less important updates;

  • batching helps React group and prioritize updates;

  • it is the foundation for startTransition() and useDeferredValue():

    javascript
    startTransition(() => { setSearchQuery(value); // low-priority update });

Summary

What batching isHow it works
A mechanism for grouping state updatesSeveral setState calls trigger one render
Enabled everywhere in React 18Even in promises, async/await, setTimeout
Improves performanceFewer unnecessary re-renders
Can be disabled via flushSync()For urgent updates
Foundation of concurrent renderingReact can optimize the render stream

In simple terms:

batching is when React waits until you "press Enter" after a series of setState calls, and does one shared render instead of a dozen small ones.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.