state
useReducer
Manages component state through a reducer function that maps (state, action) to the next state. Reach for it when state transitions are complex, involve multiple sub-values, or when the next state depends on the previous in non-trivial ways.
const [state, dispatch] = useReducer(reducer, initialArg, init?) Parameters & Behavior
| Parameter | Purpose |
|---|---|
| reducer | Pure function (state, action) => newState that describes every transition |
| initialArg | Initial state value, or the argument passed to the optional init function |
| init | Optional lazy initializer — receives initialArg and returns the initial state |
| dispatch(action) | Send an action object to the reducer to compute the next state |
Examples
function reducer(state, action) {
switch (action.type) {
case 'inc': return { count: state.count + 1 };
case 'dec': return { count: state.count - 1 };
default: throw new Error();
}
}
const [state, dispatch] = useReducer(reducer, { count: 0 }); Counter with typed actions
const [todos, dispatch] = useReducer(todosReducer, [], () => loadFromStorage()); Lazy init runs once, avoiding repeated storage reads
dispatch({ type: 'add', payload: { id: crypto.randomUUID(), text } }); Dispatching an action with a payload
const [state, dispatch] = useReducer(reducer, { status: 'idle', data: null, error: null }); Ideal shape for request state where multiple fields transition together
Gotcha
The reducer must be pure — never mutate state or perform side effects inside it. Returning the same reference from the reducer skips re-renders (Object.is check).
Related hooks
useState
Declares a piece of local state in a function component and returns the current value along with a setter. Reach for it whenever a component needs to remember a value across renders and re-render when that value changes.
useContext
Reads the current value of a React context from the nearest matching Provider above in the tree. Reach for it to share values like themes, auth, or locale without prop-drilling through every intermediate component.
useMemo
Memoizes the result of a computation between renders, recomputing only when a dependency changes. Reach for it when a calculation is genuinely expensive or when you need a stable reference (e.g. as a dep of another hook or a context value).
useSyncExternalStore
Subscribes a component to an external store in a way that is safe with concurrent rendering, preventing tearing. Reach for it when writing a library or reading from a store that lives outside React (Redux, Zustand, browser APIs, custom event emitters).