← Back to Chapters

Automatic Batching

⚛️ Automatic Batching

? Quick Overview

Automatic Batching is a major performance optimization introduced in React 18. It groups multiple state updates into a single re-render cycle, even when those updates occur inside promises, setTimeout, or native event handlers.

? Key Concepts

  • Batching: The process of grouping multiple state updates to prevent unnecessary re-renders.
  • Pre-React 18: Batching only happened inside React event handlers (e.g., onClick).
  • React 18+: Batching is automatic and happens everywhere by default.
  • Performance: Significantly reduces the "work" React needs to do to update the DOM.

? Syntax / Theory

In React 18, regardless of where you trigger state changes, React waits until the end of the event loop tick to update the view.

? View Code Example
// React 17 Behavior (Legacy)
setTimeout(() => {
  setCount(c => c + 1); // Triggers Render 1
  setFlag(f => !f);     // Triggers Render 2
}, 1000);

// React 18 Behavior (Automatic Batching)
setTimeout(() => {
  setCount(c => c + 1); // ...waits
  setFlag(f => !f);     // ...waits
  // React renders ONCE here
}, 1000);

? Code Example

Here is a complete component demonstrating batching inside an asynchronous setTimeout callback.

? View Code Example
// AutoBatchDemo.jsx
import React, { useState } from "react";

function AutoBatchDemo() {
  const [count, setCount] = useState(0);
  const [message, setMessage] = useState("Ready");

  console.log("Rendered!"); // Checks how many times we render

  const handleAsyncUpdate = () => {
    // In React 17, this setTimeout would cause 2 renders
    // In React 18, this causes only 1 render
    setTimeout(() => {
      setCount((c) => c + 1);
      setMessage("Updated inside setTimeout");
    }, 1000);
  };

  return (
    <div>
      <h4>Count: {count}</h4>
      <p>Message: {message}</p>
      <button onClick={handleAsyncUpdate}>
        Update Asynchronously
      </button>
    </div>
  );
}

export default AutoBatchDemo;

? Live Output / Explanation

Console Output

When you click the button:

  1. Initial Render: Logs "Rendered!"
  2. Click: Timer starts.
  3. After 1s: Both states change.
  4. Log: "Rendered!" (Appears only ONCE more, not twice).

? Interactive Logic

Visualizing how React groups updates:

? 1 RENDER

? Interactive Simulation

Click the buttons below to simulate how React handles state updates inside a setTimeout.

Current State

Count: 0
Flag: false

Render Count

0
Ready to simulate...

? Use Cases

  • Form Submission: Updating loading state, data state, and error state simultaneously inside a fetch promise.
  • Debouncing: Handling rapid user inputs that trigger multiple state changes.
  • Complex UI: Dashboards where one event triggers updates across multiple widgets.

? Tips & Best Practices

  • No Code Change Needed: This is automatic in React 18 if you use createRoot.
  • Opting Out: If you strictly need to render immediately after a specific update (rare), use flushSync.
  • Class Components: Automatic batching applies mostly to functional components with hooks, though behavior improves generally.

? Try It Yourself

  1. Create a component with 3 different state variables.
  2. Update all 3 inside a fetch().then() block.
  3. Add a console.log('Render') in the component body.
  4. Observe that it only logs once despite 3 updates.