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 17 batched state updates in event handlers

React 17 batches multiple updates inside event handlers by default:

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

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

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

Here, React will wait until handleClick finishes execution before it processes the state updates. As a result, handleClick will only trigger a single re-render.

CodeSandbox

React 17 did not batch state updates outside event handlers

Although React 17 batches state updates inside React events like onClick, it didn’t batch updates inside promises, setTimeout, setInterval or other native browser events:

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

  function handleClick() {
    fetchSomething().then(() => {
      // React 17 and earlier does NOT batch these because
      // they run *after* the event in a callback, not *during* it
      setCount(c => c + 1) // Causes a re-render
      setFlag(f => !f) // Causes a re-render
    });
  }

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

Here, the callback to fetchSomething will cause two re-renders – one after setCount(c => c + 1), one after setFlag(f => !f).

CodeSandbox

Sources

Tagged: React