DEV Community

Maxim Logunov
Maxim Logunov

Posted on

How React Batches State Updates to Optimize Rendering

Introduction

In React applications, managing state updates efficiently is crucial for maintaining high performance and a smooth user experience. One of React's key optimization techniques is batching state updates, which minimizes unnecessary re-renders and improves application performance. In this article, we'll explore how batching works, when it occurs, and how you can leverage it effectively in your React applications.

What is Batching?

Batching refers to React's practice of grouping multiple state updates into a single re-render for better performance. Instead of triggering a re-render for every individual state change, React can collect several updates and process them together.

// Without batching (older React versions or certain scenarios)
setCount(1); // Re-render 1
setCount(2); // Re-render 2
setCount(3); // Re-render 3

// With batching (modern React)
setCount(1);
setCount(2);
setCount(3); // Only one re-render occurs
Enter fullscreen mode Exit fullscreen mode

When Does Batching Occur?

Automatic Batching in React 18+

Starting with React 18, batching is applied automatically to all state updates regardless of where they originate:

  1. Event handlers: All updates within the same event handler are batched
  2. Async operations: Updates within promises, setTimeout, native event handlers, etc.
  3. Multiple state setters: Calls to multiple useState setters or useReducer dispatches
function handleClick() {
  setCount(c => c + 1);    // These will
  setFlag(f => !f);        // be batched into
  setName('Updated');      // a single re-render
}
Enter fullscreen mode Exit fullscreen mode

Special Cases Before React 18

Prior to React 18, batching only occurred in React event handlers. Updates inside promises, setTimeout, or native event handlers weren't batched:

// React 17 and earlier:
function handleClick() {
  // Batched (inside React event handler)
  setCount(c => c + 1);
  setFlag(f => !f);

  setTimeout(() => {
    // NOT batched (in setTimeout)
    setCount(c => c + 1);
    setFlag(f => !f);
  }, 1000);
}
Enter fullscreen mode Exit fullscreen mode

How to Control Batching

While automatic batching is generally beneficial, there might be cases where you need more control:

1. flushSync for Immediate Updates

React provides flushSync to opt-out of batching when necessary:

import { flushSync } from 'react-dom';

function handleClick() {
  flushSync(() => {
    setCount(1); // Immediate update
  });
  // DOM is updated here
  flushSync(() => {
    setFlag(true); // Immediate update
  });
  // DOM is updated again here
}
Enter fullscreen mode Exit fullscreen mode

2. unstable_batchedUpdates for Legacy Code

In older versions or special cases, you can use the (unstable) batchedUpdates API:

import { unstable_batchedUpdates } from 'react-dom';

unstable_batchedUpdates(() => {
  setCount(1);
  setFlag(true);
});
Enter fullscreen mode Exit fullscreen mode

Performance Benefits

Batching provides several performance advantages:

  1. Reduced re-renders: Fewer render passes means better performance
  2. Avoiding "tearing": Prevents partial state updates from being visible
  3. Consistent UI: Ensures the UI updates with a complete new state

Best Practices

  1. Trust React's batching: Don't try to manually optimize unless you have measurable performance issues
  2. Group related state: Consider using useReducer for complex, related state
  3. Be mindful of dependencies: Ensure effects and memoized values account for batched updates
  4. Test edge cases: Verify behavior in asynchronous scenarios

Common Pitfalls

  1. Assuming immediate updates: State setters are asynchronous
  2. Reading state right after setting it: Use the updater function form if you need the latest value
  3. Overusing flushSync: This can hurt performance by forcing too many renders

Conclusion

React's batching mechanism is a powerful optimization that works behind the scenes to keep your application performant. With React 18's improved automatic batching, developers can write more straightforward code while still benefiting from optimized rendering. Understanding how and when batching occurs helps you write more efficient React components and avoid common performance pitfalls.

By working with React's batching system rather than against it, you can build applications that are both performant and maintainable.

Top comments (0)