React/Hooks/Lesson 10
useReducer — When useState Reaches Its Limits, the Foundation of Redux
35 min·theory
This chapter
2/5
TypeScript
useReducer — When useState Reaches Its Limits, the Foundation of Redux
💡 Why Should You Learn This? — The Moment useState Gets Messy
🎯
The moment you have 5–6 `useState` calls piled up in a single component and they start influencing each other — the state-update code becomes increasingly fragile with every touch.
💼
`useReducer` consolidates those states into **a single object + dispatch(action) pattern**. Every action and the change it produces is declared in the reducer function, making the logic fully traceable.
⚡
Redux Toolkit, Zustand, and `useActionState` (React 19) all share the same mental model as `useReducer`. Understanding this hook is the natural on-ramp to all of them.
🔗
A classic interview question: 'What is the criterion for choosing between `useState` and `useReducer`?' — consider the number of state values, their complexity, and whether updates originate from multiple places.
🏢 실무에서는
Shopping carts (add item, change quantity, remove, clear all), form wizards (next, back, save, validate), collaborative canvases (add shape, move, copy, undo) — all of these fall squarely in `useReducer` territory. No matter how many action types grow, you simply add a new branch to the single reducer.
reducer · action · dispatch — 3 Key Concepts
1. Signature
- ▸
reducer: a pure function of the form (state, action) => newState - ▸
dispatch(action): calls the reducer to update state
2. Defining action types with a Discriminated Union
A union branched by the type field (tag). Inside a switch statement, the additional fields of action are inferred precisely for each case.
3. reducer — a pure function, never mutate
4. Choosing between useState and useReducer
💡 💡 useReducer Best Practices — 5 Tips
1. reducer must always be a pure function
Given the same (state, action), it must always return the same result. Side effects like fetch or setTimeout are forbidden.
2. Never mutate state
3. Define action types with a Discriminated Union
Inside a switch, the additional fields of action are inferred precisely per case.
4. Exhaustive check with never
If you add a new type to Action but forget to handle the case, you get a compile-time error.
5. Context + useReducer = mini Redux
For small apps, this is often sufficient without needing Redux.
⚡ Try It Yourself — reducer Pattern
Simulates action handling in a shopping cart reducer.
✏️ JS 코드
📟 Console output
▶ Press the Run button
⚠️ Runs in a browser sandbox — only console.log() is supported; alert/fetch are not.
Check Your Understanding
In what situations is useReducer a better fit than useState?
Read this first: useEffect
Up next: SyntheticEvent — Event Types