React Hooks Series

useReducer

The useState alternative for complex state logic. When your state has multiple sub-values or the next state depends on the previous one in non-trivial ways, useReducer keeps things predictable.

01 — What it is

01
The problem useReducer solves

When you have multiple pieces of state that change together, or state transitions that follow strict rules, managing it with several useState calls gets messy. useReducer centralises all state logic into a single pure function — the reducer.

02
The signature
const [state, dispatch] = useReducer(reducer, initialState);

// reducer      → (state, action) => newState
// initialState → the starting value
// state        → current state
// dispatch     → send an action to the reducer
The reducer must be a pure function — same input always produces same output, no side effects. Return a new object, never mutate state directly.

02 — How to use it

03
Defining a reducer
interface State {
  count: number;
  showText: boolean;
}

type Action =
  | { type: "INCREMENT" }
  | { type: "toggleShowText" };

const reducer = (state: State, action: Action): State => {
  switch (action.type) {
    case "INCREMENT":
      return { ...state, count: state.count + 1 };
    case "toggleShowText":
      return { ...state, showText: !state.showText };
    default:
      return state;
  }
};
04
Dispatching actions

You never call the reducer directly — you dispatch an action object and React calls the reducer for you. Multiple dispatches in one handler are batched into a single re-render.

// Dispatch a single action
dispatch({ type: "INCREMENT" });

// Dispatch multiple — React batches them
dispatch({ type: "INCREMENT" });
dispatch({ type: "toggleShowText" });

03 — Live demo

ReducerTutorial — interactive

One button dispatches two actions — an increment and a text toggle. Both are batched into a single re-render.

0

This text toggles with every click — dispatched alongside the increment.

04 — useState vs useReducer

SituationUse
Simple independent valuesuseState
Multiple values that change togetheruseReducer
Next state depends on previoususeReducer
State transitions follow strict rulesuseReducer
Logic needs to be testable in isolationuseReducer
Next: useContext — share state across the component tree without prop drilling.