InterviewHubPRO
Section Overview
Q280

Question 280 of 445

Part 9: React Hooks Deep Dive (262 - 316)

63%
React & Modern Frontend (445 Qs)•Part 9: React Hooks Deep Dive (262 - 316)

Is dispatch from useReducer asynchronous and does it update state immediately?

The dispatch function returned by useReducer is not asynchronous — it is a synchronous function call. When you call dispatch(action), React synchronously invokes your reducer with the current state and the action, computes the new state, and schedules a re-render. However, the state variable does not update immediately within the same render cycle. The updated state is only available in the next render.

This behavior is similar to useState's setState — React batches state updates for performance optimization, meaning the component does not re-render immediately after each dispatch call. Instead, React processes all dispatched actions and re-renders once with the final state.

Key Points

  1. dispatch is synchronous: The reducer runs immediately when dispatch is called.
  2. State update is not immediate in the current render: The state variable still holds the old value until the next render.
  3. React batches updates: Multiple dispatch calls within the same event handler result in a single re-render.
  4. Reducer is a pure function: It computes the new state without side effects.

Example demonstrating that state does not update immediately

jsx
import React, { useReducer } from 'react';

function reducer(state, action) {
switch (action.type) {
  case 'increment':
    return { count: state.count + 1 };
  default:
    return state;
}
}

function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });

const handleClick = () => {
  dispatch({ type: 'increment' });
  console.log(state.count); // Still logs the OLD value (e.g., 0), not 1
  dispatch({ type: 'increment' });
  console.log(state.count); // Still logs the OLD value (e.g., 0), not 2
};

// After re-render, state.count will be 2 (both dispatches are processed)
return (
  <div>
    <p>Count: {state.count}</p>
    <button onClick={handleClick}>Increment Twice</button>
  </div>
);
}

In the above example, even though dispatch is called twice, state.count still reflects the previous value inside the event handler. React batches both dispatches and re-renders the component once with count: 2.

How to read updated state after dispatch

If you need the updated value right after dispatching, you have several options:

  1. Use useEffect to react to state changes:
jsx
 useEffect(() => {
   console.log('Updated count:', state.count);
 }, [state.count]);
  1. Compute the next state manually:
jsx
 const handleClick = () => {
   const nextState = reducer(state, { type: 'increment' });
   console.log('Next state will be:', nextState.count);
   dispatch({ type: 'increment' });
 };
  1. Use useRef to track the latest state:
jsx
 const stateRef = useRef(state);
 useEffect(() => {
   stateRef.current = state;
 }, [state]);

Note: This behavior is by design in React. The dispatch function itself has a stable identity (it doesn't change between re-renders), which makes it safe to omit from useEffect dependency arrays.