Reducer-Based Toggle Component
Learn how to build a reusable toggle component whose behavior is driven entirely by a reducer, turning a simple boolean flag into a predictable state machine.
UI toggles often begin as trivial useState booleans, but as an application grows, they accumulate conditional rules, forcing the toggle on for certain roles, suppressing off transitions during loading, resetting after submission, and more. When this logic is scattered across event handlers and effects, behavior becomes unpredictable and difficult to maintain. The State Reducer pattern addresses this by moving behavioral logic out of the component body and into a reducer that explicitly defines state transitions. In this lesson, we build a reducer-driven toggle with explicit, testable state transitions. In the next lesson, we extend it to support external reducer overrides.
Reducer design for a toggle
A reducer-based component begins with a defined internal behavioral contract. For a simple toggle, the contract consists of the following elements:
State definition: The toggle maintains a minimal, deterministic state shape.
{ isOn: boolean }
This keeps state modeling simple and focused.
Action vocabulary: Actions describe what happened rather than what to do. A toggle typically supports:
"TOGGLE""TURN_ON""TURN_OFF"
These declarative labels allow the reducer to interpret intent without embedding logic in the UI.
Transition logic (Reducer): The reducer defines how each action transforms the current state.
Examples:
"TURN_ON"→{ isOn: true }"TURN_OFF"→{ isOn: false }"TOGGLE"→ flips the boolean
This makes all behavior auditable and easy to test.
State management via ...