useReducer is a React Hook that lets you add a reducer to your component for managing complex state logic.
Parameters
(state: S, action: A) => S
required
The reducer function that specifies how the state gets updated. It must be pure, should take the state and action as arguments, and should return the next state. State and action can be of any types.
I
required
The value from which the initial state is calculated. It can be a value of any type. How the initial state is calculated from it depends on the
init argument.(initialArg: I) => S
Optional initializer function. If provided, the initial state will be set to
init(initialArg). Otherwise, it’s set to initialArg.This is useful when the initial state needs to be computed from props or when you want to extract the logic for resetting state.Returns
useReducer returns an array with exactly two values:
S
The current state. During the first render, it’s set to
init(initialArg) or initialArg (if no init function).Dispatch<A>
The
dispatch function that lets you update the state to a different value and trigger a re-render.The dispatch function accepts an action object and has no return value.Usage
Basic counter with reducer
Todo list with reducer
Using the init function
When to use useReducer
- Use useState
- Use useReducer
useReducer when:
- You have complex state logic with multiple sub-values
- The next state depends on the previous one
- You want to optimize performance by passing dispatch down instead of callbacks
- You prefer having all state update logic in one place
Common Patterns
Action with payload
Reducer with multiple fields
Combining with Context
Immer for immutable updates
TypeScript
With discriminated unions
Troubleshooting
My reducer state shows the old value
State updates are asynchronous. The updated value will be available in the next render:My reducer doesn’t update the UI
Make sure you’re returning a new state object, not mutating the existing one:Dispatch is causing too many re-renders
Make sure you’re not calling dispatch during render:My reducer is getting complex
Consider:- Breaking it into multiple smaller reducers
- Using a state management library (Redux, Zustand, Jotai)
- Moving some logic into custom hooks
- Using Immer for simpler immutable updates