Home   reactjs  

Synchronous and Asynchronous State Updates and batch updates in React

React batches state updates to optimize performance, especially when multiple setState calls are made within the same event loop. This means if you call setState multiple times in a synchronous code block (like within an event handler), React will group those updates together and perform a single re-render.

Here's a detailed explanation with an example:

Example with Multiple setState Calls

Let's say you have a component with two states, s1 and s2:

import React, { Component } from 'react';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      s1: 0,
      s2: 0
    };
  }

  updateStates = () => {
    this.setState({ s1: this.state.s1 + 1 });
    this.setState({ s2: this.state.s2 + 1 });
  };

  render() {
    console.log('Rendering...');
    return (
      <div>
        <p>s1: {this.state.s1}</p>
        <p>s2: {this.state.s2}</p>
        <button onClick={this.updateStates}>Update States</button>
      </div>
    );
  }
}

export default MyComponent;

How React Handles This

  1. Batching: When updateStates is called, both setState calls are made synchronously. React batches these updates to optimize the rendering process.
  2. Single Re-render: Instead of re-rendering twice (once for each setState call), React schedules a single re-render after all state updates are processed.

Why This Matters

Batching state updates is crucial for performance. It ensures that your component only re-renders once, even if multiple state changes occur. This reduces unnecessary renders and makes your application more efficient.

React's Update Mechanism

React batches state updates automatically in event handlers and lifecycle methods but not in asynchronous code like setTimeout, promises, or async/await. For asynchronous updates, React 18 introduced automatic batching for updates, which helps handle this more efficiently.

Example with Asynchronous Code

updateStatesAsync = () => {
  setTimeout(() => {
    this.setState({ s1: this.state.s1 + 1 });
    this.setState({ s2: this.state.s2 + 1 });
  }, 1000);
};

In React 17 and earlier, the above asynchronous setState calls would not be batched, leading to two separate re-renders. However, with React 18 and the introduction of automatic batching, even these updates are batched, resulting in a single re-render.

React 18 Automatic Batching Example

import React, { Component } from 'react';
import ReactDOM from 'react-dom/client';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      s1: 0,
      s2: 0
    };
  }

  updateStatesAsync = () => {
    setTimeout(() => {
      this.setState({ s1: this.state.s1 + 1 });
      this.setState({ s2: this.state.s2 + 1 });
    }, 1000);
  };

  render() {
    console.log('Rendering...');
    return (
      <div>
        <p>s1: {this.state.s1}</p>
        <p>s2: {this.state.s2}</p>
        <button onClick={this.updateStatesAsync}>Update States Asynchronously</button>
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<MyComponent />);
Published on: Jul 04, 2024, 01:06 PM  
 

Comments

Add your comment