The useReducer hook provides predictable state management for complex state logic. Here are the essential patterns.
Basic Usage#
Actions with Payloads#
Lazy Initialization#
Form State Management#
Async Actions Pattern#
Immer Integration#
Context + Reducer Pattern#
Action Creators#
Multiple Reducers#
Middleware Pattern#
Best Practices#
When to Use:
✓ Complex state logic
✓ Multiple sub-values
✓ State depends on previous state
✓ Testable state updates
Patterns:
✓ Discriminated unions for actions
✓ Action creators for reusability
✓ Lazy initialization
✓ Context for global state
Performance:
✓ Stable dispatch reference
✓ Split contexts (state/dispatch)
✓ Memoize selectors
✓ Use Immer for deep updates
Avoid:
✗ Over-engineering simple state
✗ Mutating state directly
✗ Missing default case
✗ Huge monolithic reducers
Conclusion#
The useReducer hook provides predictable state management through explicit actions and pure reducer functions. Use it for complex state logic, form management, or when state updates depend on previous values. Combine with Context for global state management and consider Immer for easier immutable updates. The dispatch function is stable across renders, making it ideal for passing to child components.