Capítulo 31 de 116
When a component's event handlers each update state in several places with related logic, consolidating all that logic into one reducer function outside the component — dispatching named "actions" instead of calling setters directly — makes the component's handlers shorter and the state transitions easier to test and reason about together.
setState calls to dispatch(action) calls in event handlers, (2) write a reducer function that takes (state, action) and returns the next state, (3) replace useState with useReducer(reducer, initialState) in the component.{ type: 'added', text }), not "what should change" — the reducer, not the caller, decides how the state actually updates for a given action. This separates what the user did from how state responds.(state, action) pair, it must return the same next state, with no side effects — this is what makes reducers easy to unit test in isolation, without rendering any component.useReducer vs. useState: useReducer trades slightly more setup (writing the reducer function, action shapes) for centralizing update logic in one place instead of scattering it across every event handler — most valuable once a component has several related state updates or a handler that updates multiple pieces of state together.switch focused and avoid deeply nested conditionals; when the update logic against nested state gets complex, Immer works with useReducer the same way it does with useState (Ch 25) to let case bodies read like direct mutation while staying safe.function tasksReducer(tasks, action) {
switch (action.type) {
case 'added':
return [...tasks, { id: action.id, text: action.text, done: false }];
case 'deleted':
return tasks.filter(t => t.id !== action.id);
default:
throw Error('Unknown action: ' + action.type);
}
}
const [tasks, dispatch] = useReducer(tasksReducer, []);
useReducer when a component's state updates are numerous, related, or scattered across handlers — not as a default replacement for simple, independent useState calls.default case should throw (or otherwise loudly fail) on an unrecognized action type — silent no-ops hide bugs.expect(reducer(state, action)).toEqual(nextState)) precisely because they're pure functions with no component or DOM involved.