🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
REFERENCEreact

react Documentation

LOADING ENGINE...

Asynchronous State

AI & DATA SCIENCE // asynchronous-state

State updates in React are asynchronous and batched, meaning the updated value isn't available immediately after calling the setter, and multiple updates in the same event are combined into a single re-render.

Syntax

setState(newValue); // doesn't update immediately within the same function call

Deep Dive Course

Calling a state setter doesn't synchronously update the state variable available in the currently-executing function — React schedules the update and applies it before the next render, which means code immediately after a setState call, within that same function, still sees the old value. React also batches multiple state updates that occur within the same event handler, and since React 18, within most other contexts too, into a single re-render, rather than re-rendering separately after each individual update, both for efficiency and to avoid showing intermediate, inconsistent UI states partway through a sequence of related updates.

1Understanding Asynchronous State

Calling a state setter doesn't synchronously update the state variable available in the currently-executing function — React schedules the update and applies it before the next render, which means code immediately after a setState call, within that same function, still sees the old value. React also batches multiple state updates that occur within the same event handler, and since React 18, within most other contexts too, into a single re-render, rather than re-rendering separately after each individual update, both for efficiency and to avoid showing intermediate, inconsistent UI states partway through a sequence of related updates.

💡

If you need to react to a state value right after it changes, put that logic inside a useEffect watching that specific value, rather than expecting the updated value to be immediately available on the very next line after calling its setter.

editor.html
import { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // still logs the OLD value
  };
  return <button onClick={handleClick}>Count: {count}</button>;
}
localhost:3000

2Practical Example

Here is a real-world application of Asynchronous State showing how it is used in production React code.

editor.html
import { useState } from 'react';

function Example() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);
  const handleClick = () => {
    setA(a + 1);
    setB(b + 1);
    console.log('This causes only ONE re-render, not two');
  };
  return <p>{a} / {b}</p>;
}
localhost:3000

3Best Practices

Follow these guidelines when working with Asynchronous State:

1. Never assume a state variable reflects its new value on the line immediately following its setter call within the same function execution

2. Use useEffect with the relevant value in its dependency array to run logic specifically in response to that value having changed, rather than expecting an immediate synchronous update

3. Use the functional updater form when a new state value depends on the current one, since it always receives the latest pending value regardless of batching

⚠️

Tip: If you need to react to a state value right after it changes, put that logic inside a useEffect watching that specific value, rather than expecting the updated value to be immediately available on the very next line after calling its setter.

editor.html
import { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // still logs the OLD value
  };
  return <button onClick={handleClick}>Count: {count}</button>;
}
localhost:3000

Examples

Example 01Basic Usage
import { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // still logs the OLD value
  };
  return <button onClick={handleClick}>Count: {count}</button>;
}
Example 02Advanced Example
import { useState } from 'react';

function Example() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);
  const handleClick = () => {
    setA(a + 1);
    setB(b + 1);
    console.log('This causes only ONE re-render, not two');
  };
  return <p>{a} / {b}</p>;
}

Best Practices

  • Never assume a state variable reflects its new value on the line immediately following its setter call within the same function execution
  • Use useEffect with the relevant value in its dependency array to run logic specifically in response to that value having changed, rather than expecting an immediate synchronous update
  • Use the functional updater form when a new state value depends on the current one, since it always receives the latest pending value regardless of batching

Interview Question

Why does React batch multiple state updates within the same event handler into a single re-render, rather than re-rendering after each individual setState call?

Hint: Think about both the performance cost of extra renders, and what an intermediate, partially-updated UI state might look like if renders weren't batched.

If React re-rendered immediately after every single setState call, updating two related pieces of state in the same event handler would trigger two separate, sequential render-and-commit cycles, wasting rendering work on an intermediate state that the user would never actually need to see, since only the final combined result after both updates genuinely matters. Batching multiple updates from the same event handler together into one single re-render avoids that redundant intermediate work entirely, computing the final render just once using the combined effect of all the updates from that handler at once, which is both more efficient and avoids briefly showing a half-updated UI reflecting only one of two related changes that should always appear together, like updating a form's value and its corresponding validation error message in the same handler.

Exercises

MediumPractice using Asynchronous State in a real scenario.
View Solution
import { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // still logs the OLD value
  };
  return <button onClick={handleClick}>Count: {count}</button>;
}

Frequently Asked Questions

Why does React batch multiple state updates within the same event handler into a single re-render, rather than re-rendering after each individual setState call?

If React re-rendered immediately after every single setState call, updating two related pieces of state in the same event handler would trigger two separate, sequential render-and-commit cycles, wasting rendering work on an intermediate state that the user would never actually need to see, since only the final combined result after both updates genuinely matters. Batching multiple updates from the same event handler together into one single re-render avoids that redundant intermediate work entirely, computing the final render just once using the combined effect of all the updates from that handler at once, which is both more efficient and avoids briefly showing a half-updated UI reflecting only one of two related changes that should always appear together, like updating a form's value and its corresponding validation error message in the same handler.

Related Functions

usestateusereduceruseeffect