useReducer is a powerful alternative to useState for complex state logic. Here's how to use it effectively.
Basic useReducer#
Action Payloads#
Lazy Initialization#
Complex State#
Form State Management#
Action Creators#
useReducer with Context#
TypeScript with useReducer#
useReducer vs useState#
Best Practices#
Reducer Design:
✓ Keep reducers pure
✓ Return new state objects
✓ Handle unknown actions gracefully
✓ Use action type constants
State Structure:
✓ Normalize nested data
✓ Keep state minimal
✓ Derive values when possible
✓ Initialize with all fields
Actions:
✓ Use descriptive action types
✓ Keep payload minimal
✓ Use action creators
✓ Document action shapes
Avoid:
✗ Side effects in reducers
✗ Mutating state directly
✗ Complex logic in components
✗ Over-engineering simple state
Conclusion#
useReducer excels at managing complex state with clear action-based updates. Use it when state has multiple sub-values, when next state depends on previous state, or when you want testable, predictable state logic. Combine with Context for global state management, and use TypeScript for type-safe actions and state.