• Post author:
  • Reading time:13 mins read
You are currently viewing Understanding useState Batching in React – A Deep Dive into State Updates

Are you frustrated with local states not working the way you expect them to in your React application🤔 You’re not alone…

React can sometimes feel like it’s playing tricks on you, especially when those state updates don’t behave as expected.

But don’t worry, I’m here to untangle the mystery.

React’s useState hook is a fundamental part of modern React development, allowing you to add state to functional components and make your UI interactive and dynamic.

However, the intricacies of how state updates are batched and handled can sometimes lead to unexpected behavior, leaving even seasoned developers scratching their heads.

In this detailed post, we’re going to understand why this happens. To demonstrate what’s going on and where the trick is, I’ll be creating a simple counter application.

I suggest you follow along with me, and then we’ll manipulate the code to simulate these state behavioral issues. Get ready for some fun and enlightening React debugging.

Before that don’t forget the cup of coffee on the side.. cheers 🍵

Also Read : Understanding Docker Architecture and its Components In Depth



Creating a very basic Simple Counter application

Let’s dive into building a basic React counter application.

This will serve as our starting point for exploring state behavior in React.

Our goal is to create a simple user interface that displays a counter value, which users can easily manipulate using increment and decrement buttons.

We’ll start by setting an initial counter value, and then we’ll add functionality to increase or decrease this value when the respective buttons are clicked.

This foundational example will help us illustrate key concepts related to state management and updates in React, setting the stage for deeper insights into potential pitfalls and best practices.

So lets start with the setup ✌🏻


Initial Setup of the React Application


First, create a new React project using Create React App (if you haven’t already)

npx create-react-app simple-counter
cd simple-counter


Next, modify App.js to include our counter logic:

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

const App = () => {
  const [count, setCount] = useState(18);

  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);

  return (
    <div className="application">
      <h1>Counter</h1>
      <div className="counter-display">
        {count}
      </div>
      <button className="counter-button" onClick={increment}>Increment</button>
      <button className="counter-button" onClick={decrement}>Decrement</button>
    </div>
  );
}

export default App;


And some basic CSS in App.css

.application {
  text-align: center;
  margin-top: 50px;
}

.counter-display {
  font-size: 48px;
  margin: 20px 0;
}

.counter-button {
  font-size: 16px;
  padding: 10px 20px;
  margin: 5px;
  cursor: pointer;
  border: none;
  background-color: #4CAF50;
  color: white;
  border-radius: 5px;
}

.counter-button:hover {
  background-color: #45a049;
}


Unexpected Behavior: Multiple State Updates in React

Now, let’s explore a common pitfall. What happens if we try to increment the counter multiple times in a single function call?

Stop scrolling and think of the possible answer of the counter. You don’t need to be correct… just give a thought.

const increment = () => {
  setCount(count + 1);
  setCount(count + 1);
  setCount(count + 1);
}

Increase by 3 right? so the counter will show 18+3 or 21 that’s what you might have calculated?

So, you might have expected the counter to increase by 3 when the increment button is clicked.

However, this is not the case. Instead, the counter only increases by 1. Strange right? but lets understand Why so.


Understanding State Batching

React batches state updates for performance reasons. When setCount(count + 1) is called multiple times within the same function, each call uses the same initial value of count due to how React batches these updates.

In this case, each setCount(count + 1) is evaluated with the count value from the current render cycle, which is 18. Therefore, the state is set to 19 three times, and the final rendered value is 19.


The Functional Update Form

To achieve the desired behavior of incrementing by 3, we need to use the functional form of the setCount updater function.

This form ensures that each state update is based on the most recent state value, not the initial value from the current render cycle.

Here’s the updated increment function:

const increment = () => {
  setCount(prevCount => prevCount + 1);
  setCount(prevCount => prevCount + 1);
  setCount(prevCount => prevCount + 1);
}

In this version, each setCount call receives the updated state value from the previous call.

So, the first call increments count from 18 to 19, the second call increments from 19 to 20, and the third call increments from 20 to 21.

As a result, clicking the increment button now correctly increases the counter by 3 👍


Practical Example: Complete Code


Here’s the complete code with the functional update form:

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

const App = () => {
  const [count, setCount] = useState(18);

  const increment = () => {
    setCount(prevCount => prevCount + 1);
    setCount(prevCount => prevCount + 1);
    setCount(prevCount => prevCount + 1);
  };

  const decrement = () => setCount(count - 1);

  return (
    <div className="App">
      <h1>Counter</h1>
      <div className="counter-display">
        {count}
      </div>
      <button className="counter-button" onClick={increment}>Increment</button>
      <button className="counter-button" onClick={decrement}>Decrement</button>
    </div>
  );
}

export default App;


Key Understandings & Conclusion

React’s state management is powerful but has some complexities that can catch even experienced developers off guard. Here’s what we’ve learned-

React batches state updates for performance reasons. This means that if you make multiple setState calls within the same function, React processes these calls together using the initial state value from the current render cycle.

This batching can lead to unexpected results if you’re not aware of it 😂

To ensure that each state update is based on the most recent state, use the functional form of the updater function. This method is crucial when applying multiple updates in sequence, as it ensures that each update correctly accounts for the state changes from previous updates.

Understanding these concepts is essential, especially during job interviews. Questions about state updates and batching are common in React interviews, and demonstrating your knowledge of these concepts shows a deep understanding of React’s behavior and performance optimizations.

By grasping how state batching works and knowing when to use functional updates, you can avoid common pitfalls and write more predictable, reliable code.

This knowledge not only improves your everyday coding but also enhances your performance in technical interviews, showcasing your proficiency with React.

Stay tuned for more insightful and valuable discussions on Software Engineering. In the meantime, follow us on X (formally Twitter) for more updates and interesting content 🔥

This:

Sayak Mukherjee

Hello, fellow tech enthusiasts. I'm Sayak, welcoming you to TheTechDelta. With a passion for tech innovations, I aim to share insights and empower you with impactful knowledge and tools. Whether you're a newbie or an expert, join us as we unravel the wonders of the tech universe together.

Leave a Reply