React Hooks
React useReducer Hook
useReducer manages state through a reducer function: you dispatch an action describing what happened, and the reducer returns the next state. It suits state with several fields that change together, or transitions with real rules.
What is useReducer Hook in React?
useReducer manages state through a reducer function: you dispatch an action describing what happened, and the reducer returns the next state. It suits state with several fields that change together, or transitions with real rules.
Why useReducer Hook matters
Once a component has five useState calls that must update in a coordinated way, a reducer puts all the transition logic in one testable pure function instead of scattering it across handlers.
useReducer Hook example
const initial = { status: 'idle', data: null, error: null };
function reducer(state, action) {
switch (action.type) {
case 'FETCH_START': return { ...state, status: 'loading', error: null };
case 'FETCH_SUCCESS': return { status: 'success', data: action.payload, error: null };
case 'FETCH_ERROR': return { ...state, status: 'error', error: action.error };
default: return state;
}
}
function JobList() {
const [state, dispatch] = useReducer(reducer, initial);
useEffect(() => {
dispatch({ type: 'FETCH_START' });
fetch('/api/jobs')
.then(r => r.json())
.then(d => dispatch({ type: 'FETCH_SUCCESS', payload: d }))
.catch(e => dispatch({ type: 'FETCH_ERROR', error: e.message }));
}, []);
if (state.status === 'loading') return <Spinner />;
if (state.status === 'error') return <p>{state.error}</p>;
return <ul>{state.data?.map(j => <li key={j.id}>{j.title}</li>)}</ul>;
}How this works
Impossible combinations — loading and error at once — cannot occur, because each action produces one complete next state. The reducer is a pure function you can unit test without rendering anything.
Key points to remember
- dispatch has a stable identity, so it never needs to be a useCallback dependency.
- Reducers must be pure — no fetches, no random values, no mutation.
- A third argument to useReducer lazily computes the initial state.
useState vs useReducer
| Use useState when | Use useReducer when |
|---|---|
| One or two independent values | Several fields that change together |
| Updates are simple assignments | Transitions follow rules worth naming |
| Logic lives fine in the handler | You want logic testable in isolation |
| No need to pass updaters deep | dispatch is stable and easy to pass down |
Common mistakes with useReducer Hook
- Mutating state inside the reducer instead of returning a new object.
- Performing side effects in the reducer — put them in the effect or handler that dispatches.
- Reaching for a reducer for a single boolean toggle.
React useReducer Hook— Interview Questions & FAQs
When should I use useReducer instead of useState?+
When several pieces of state change together, when the next state depends on the previous in non-trivial ways, or when you want the transition logic in a pure function you can test. A single independent value is better served by useState.
