State Machine Pattern for UI Logic
Modeling a component's behavior as a finite set of distinct states and explicit transitions between them, instead of scattered boolean flags.
A state machine replaces a set of boolean flags with one state and defined transitions.
A state machine is like a well-designed vending machine's internal logic: it can only be in one specific mode at a time — waiting for coins, dispensing, out of stock — and it only accepts the specific inputs that are valid for its current mode, refusing to even consider a 'dispense' button press while it's still in 'waiting for coins' mode, rather than a poorly-designed machine that tracks a pile of independent switches that could theoretically all be flipped on at once, leading to nonsensical states nobody actually designed for.
Key Concepts
let isLoading = false;
let isError = false;
let isSuccess = false;
let data = null; const machine = {
idle: { FETCH: 'loading' },
loading: { SUCCESS: 'success', FAILURE: 'failure' },
success: { FETCH: 'loading' },
failure: { FETCH: 'loading', RETRY: 'loading' }
}; function transition(state, event) {
return machine[state]?.[event] ?? state; // ignore illegal events
} let state = 'idle';
state = transition(state, 'FETCH'); // 'loading'
state = transition(state, 'SUCCESS'); // 'success'
state = transition(state, 'SUCCESS'); // 'success' -- ignored switch (state) {
case 'idle': return <Button onClick={fetch}>Load</Button>;
case 'loading': return <Spinner />;
case 'success': return <List items={data} />;
case 'failure': return <Error onRetry={retry} />;
}