• Angular
  • React
  • NextJs
  • Sass

Automatic Batching in React 18

By Webrecto, October 07, 2023

Introduction

Automatic Batching is a new feature of ReactJS, It was introduced in the React 18 version. Without automatic batching, React was re-rendered to update every state and component. In React 17, and old versions only support batching for browser events, and native event handlers were not batched.

In the old version, the application was facing many problems like performance, page speed, and multiple state updates in a single re-render. For a better solution, React uses a batching technique to solve this problem. According to this technique in the react application, it is updated to multiple states and components into a single re-render for better performance.

Automatic Batching in React

What is Automatic Batching?

Automatic Batching is a specific technique in React for improving application performance and page speed by reducing unnecessary re-renders.

Automatic Batching means, React groups multiple state updates into a single re-render for better performance. It will enabled batching of all the state updates regardless of where they are called. The states and components are updated automatically inside React event handlers and updates inside a promise, setTimeout, and native event handlers.

Note: In React 18, automatic batching is enabled.

React v18 ensures that state updates invoked from any location will be batched by default. This will batch state updates, including native event handlers, asynchronous operations, timeouts, and intervals.

In the latest version, we use 'ReactDOM.createRoot' API which will automatically batch all the state updates for us.

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
  // <React.StrictMode>
    <App />
  // </React.StrictMode>
);

We can remove React.StrictMode from index.tsx file.

// After: updates inside of timeouts, promises,
// native event handlers or any other event are batched.
setTimeout(() => {
  setCount(count => count + 1);
  setFlag(toggle => !toggle);

  // React will only re-render once at the end (that's batching!)
}, 1000);

The Problem with React 17 and Prior

In React 17 and prior, React automatically batches any state updates only inside React event handlers like a click or change.

// Before: only React events were batched.
setTimeout(() => {
  setCount(count => count + 1);
  setFlag(toggle => !toggle);

  // React will render twice, once for each state update (no batching)
}, 1000);

React will render twice, once for each state update.

Using Automatic Batching

The Automatic Batching technique is used to improve application performance. When we work on small projects it is not the impact of the re-rendering process, But in a large application, it will slow application when the re-rendering process is multi time. In React 18, state updates invoked by any location will be batched by default.

In the application, we can use 3 types of event listeners to use the update state.

1) Event Handlers

We use click events for updates to two states. When the fire clicks the event from the button, both states will update in a single re-renderer.

const clickEvent=()=>{
    setCount((count) => count + 1);
    setToggle((toggle) => !toggle);
  }

2) Asynchronous Operations

We can update both states asynchronous in the event handler. When the button is clicked, state values are printed in the browser.

const handleAsync=()=>{
    fetch("https://jsonplaceholder.typicode.com/todos/2").then(() => {
      setCount((count) => count + 1);
      setToggle((toggle) => !toggle);
    });
  }

3) Timeouts

In handling timeout events, we use the setTimeout timer to update two states in one re-renderer.

const handleTimeOut=()=>{
    setTimeout(() => {
      setCount((count) => count + 1);
      setToggle((toggle) => !toggle);
    }, 100);
  }

Benefits of Automatic Batching

In large React applications, Automatic Batching has several benefits. It improves application performance.

  • 1: Automatic batching enhances user experience by providing smooth and seamless transitions between UI updates.
  • 2: It prevents bugs by ensuring that your component always renders consistent and complete states.
  • 3: In React, batching helps to reduce the number of re-renders that happen when a state changes, when you call setState.
  • 4: It provides performance by avoiding unnecessary re-rendering.
  • 5: Automatic batching is enabled, removing the need to manually batch updates in the application or library code.

How To Stop Automatic Batching?

Reactjs provides a method flushSync() to stop automatic batching in applications. It is imported from the 'react-dom' library.

import { flushSync } from 'react-dom';

The flushSync() method allows us to force a re-render for a specific state update. We can call the flushSync() method inside the event handler for stop batching.

const clickEvent=()=>{
    flushSync(()=>{ 
      setCount((count) => count + 1); // react will create a re-render here
    })
    setToggle((toggle) => !toggle);  // react will create a re-render here
  }

In the above code, we are using flushSync() method to stop automatic batching. When the event is invoked, React will update the DOM once at flushSync() and update the DOM again at setToggle((toggle) => !toggle) avoiding the batching.

Complete Example

In the example, we are using 3 buttons Event Handler, Async Handler, Timeout Handler to update two states inside the event handler method with the help of useState hooks. Both states update in a single re-render.

App.tsx

import { useState } from "react";
import './App.css';

function App() {
  const [count, setCount] = useState(0);
  const [toggle, setToggle] = useState(false);
  
  const clickEvent=()=>{
    setCount((count) => count + 1);
    setToggle((toggle) => !toggle);
  }

  const handleAsync=()=>{
    fetch("https://jsonplaceholder.typicode.com/todos/2").then(() => {
      setCount((count) => count + 1);
      setToggle((toggle) => !toggle);
    });
  }

  const handleTimeOut=()=>{
    setTimeout(() => {
      setCount((count) => count + 1);
      setToggle((toggle) => !toggle);
    }, 100);
  }

  return (
    <div className="App">
      <h2>Automatic Batching</h2>

      <p>Count: {count}</p>
      <p style={{ color: toggle ? "blue" : "black" }}>Toggle: {toggle.toString()}</p>

      <button onClick={clickEvent}> Event Handler </button>
      <button onClick={handleAsync}> Async Handler </button>
      <button onClick={handleTimeOut}> Timeout Handler </button>
    </div>
  );
}

export default App;

Find the print screen of the output.

Automatic Batching Example

Reference

Download Source Code