useReducer — Scaling State Logic
If useState is a notepad for quick notes, then useReducer is the main ledger. It's needed not when there's a lot of data, but when the logic of their change becomes confusing.
1. Problem: " Spaghetti " of States
Imagine a complex game. A player has health, mana, inventory, and status.
- If we use
useState, then on every enemy hit we need to callsetHealth, check if the player died, callsetStatus('dead'), resetsetMana(0)... - This giant
if-elselives right inside your visual part (JSX). This is bad.
2. Analogy: Professional Kitchen
Imagine you're the Head Chef.
- Action (Order): The waiter brings a check: " Table #5, two pastas, one juice " . The waiter doesn't teach you to cook, they just report a fact: " Something happened " .
- Dispatch (Waiter): This is the intermediary. They take your order (Action) and carry it to the kitchen.
- Reducer (Kitchen): This is an isolated place where chefs (your logic) look at the check and by recipes turn old products (current State) into ready dishes (new State).
- State (Dish): What ultimately ends up on the guest's table (on the user's screen).
3. Transition from " HOW " to " WHAT "
This is the main shift in thinking:
- useState (Imperative): " Take the current number, add 1 and save " .
- useReducer (Declarative): " An event 'Button click' happened. Reducer, decide yourself what to do with it " .
4. Why Does This Make Code Cleaner?
- Isolation: All your business logic (calculations, conditions, validation) is moved to one pure function
reduceroutside the component. - Predictability: Reducer is a pure function. If you give it the same data and the same event, it will always return the same result. This is damn easy to test.
- Action History: Looking at event types (
type: 'LOGIN_SUCCESS',type: 'LOGOUT'), any developer will immediately understand what your application can do.
Mastering useReducer, you'll stop fearing 'monstrous' forms and complex interfaces. You'll just describe events, and leave logic to the professional 'chef'.