sajad torkamani

Credit: mostly taken from this post.

What is batching?

Batching is when React groups multiple state updates into a single re-render for better performance.

React 18 batches all state updates, inside or outside event handlers

If you use the new createRoot API, React 18 will batch all state updates, wherever they originate from.

In all the following examples, React 18 will batch the state updates into a single re-render.

Promise callback:

function App() {
  const [count, setCount] = useState(0)
  const [flag, setFlag] = useState(false)

  function handleClick() {
    fetchSomething().then(() => {
      // React 18 and later DOES batch these:
      setCount(c => c + 1)
      setFlag(f => !f)
      // React will only re-render once at the end (that's batching!)
    });
  }

  return (
    <div>
      <button onClick={handleClick}>Next</button>
      <h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
    </div>
  );
}

Normal event handler:

function handleClick() {
  setCount(c => c + 1)
  setFlag(f => !f)
  // React will only re-render once at the end (that's batching!)
}

setTimeout callback:

setTimeout(() => {
  setCount(c => c + 1)
  setFlag(f => !f)
  // React will only re-render once at the end (that's batching!)
}, 1000)

Native browser events:

elm.addEventListener('click', () => {
  setCount(c => c + 1)
  setFlag(f => !f)
  // React will only re-render once at the end (that's batching!)
})

Sandbox

A single event handler can batch state updates multiple times

In the following example, the handleClick handler will trigger two batched state updates:

  function handleClick() {
    // 1. These two are batched together
    setCount((c) => c + 1) // React doesn't re-render yet
    setFlag((f) => !f) // React doesn't re-render yet

    new Promise((resolve) => {
      setTimeout(() => {
        // 2. Because these two are inside the same callback, they'll be batched together
        setCount((c) => c + 1) // React doesn't re-render yet
        setFlag((f) => !f) // React doesn't re-render yet
        // The second state updates are batched & React re-renders
      }, 2000)
    })

    // The first states updates are batched & React re-renders
  }

Sources / related

Tagged: React