← Back to the Build Your Homepage series
⚛️
EPISODE 04
Reducer pattern · dispatch · actions · when over useState

useReducer

Handle complex state with useReducer — a tiny reducer function and dispatched actions. Predictable, testable, and great for multi-step state.

useReducerdispatchactionsRedux pattern
Duration
About 2 hours
Level
📊 Intermediate
Prerequisite
🎯 react-02
OUTCOME
A to-do list managed by a typed reducer with action types

What you'll learn

  • 1Write a reducer function: (state, action) => newState
  • 2Dispatch actions instead of calling many setters
  • 3Use a discriminated-union Action type for type safety
  • 4Choose useReducer over useState for complex, interrelated state

1. Reducer Shape

tsx
type State = { count: number; step: number };
type Action =
  | { type: "increment" }
  | { type: "decrement" }
  | { type: "set-step"; step: number }
  | { type: "reset" };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "increment": return { ...state, count: state.count + state.step };
    case "decrement": return { ...state, count: state.count - state.step };
    case "set-step":  return { ...state, step: action.step };
    case "reset":     return { count: 0, step: 1 };
  }
}

2. Use the Reducer

tsx
function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0, step: 1 });
  return (
    <div>
      <p>{state.count}</p>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
      <input type="number" value={state.step}
             onChange={e => dispatch({ type: "set-step", step: +e.target.value })} />
      <button onClick={() => dispatch({ type: "reset" })}>reset</button>
    </div>
  );
}

3. useState vs useReducer

PickWhen
useState1–2 simple values, updates are independent
useReducerMultiple values that change together, complex update logic, you want to test the reducer in isolation
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗