Lesson 11 of 80
State logic expressed as a pure function of (current state, action) to next state — which is exactly the JavaScript track's `reduce`, wearing a React hat.
14 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 2
How does a useReducer reducer function map onto the shape of Array.prototype.reduce's callback?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
useReducer(reducer, initialState) gives you [state, dispatch]. Instead of calling many separate setters, you dispatch a plain object describing what happened, and one function — the reducer — decides what the new state should be.
function reducer(state, action) {
switch (action.type) {
case "increment": return { count: state.count + 1 };
case "decrement": return { count: state.count - 1 };
case "reset": return { count: 0 };
default: throw new Error(`Unknown action: ${action.type}`);
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<button onClick={() => dispatch({ type: "increment" })}>{state.count}</button>
);
}
Notice the shape: (accumulator, item) => newAccumulator from the JavaScript track's reduce is exactly (state, action) => newState here. dispatch({ type: "increment" }) is one item in a stream of actions; the reducer is the step function; state is the running accumulator. useReducer is reduce, running over time instead of over an array.
dispatch({ type: 'increment' }) sends an action — a plain object describing what happened.
state directly, no side effects (fetching, logging) inside it — same rule as reduce's step function, for the same reason: React may call it more than once (Strict Mode) or discard a call, and impurity breaks that.dispatch's identity is stable across renders (React guarantees this), unlike a plain function you'd define inline — this makes it safe to pass down to deeply nested children without triggering React.memo to think it changed.useReducer and useState aren't different mechanisms — useState is actually implemented in terms of the same primitive useReducer is; picking one is a code-organization choice, not a performance one."When would you reach for useReducer over useState?" checks whether you can identify the "state transition" shape in real UI logic — and connecting it explicitly back to reduce is a strong signal you see the underlying pattern, not just two separate APIs to memorize.