patternModeratepending
State machine pattern -- explicit transitions prevent invalid states
Viewed 0 times
state machinetransitionsXStatestatechartfinite automataexplicit state
Problem
Complex state with implicit transitions leads to impossible states, forgotten edge cases, and hard-to-reproduce bugs. Boolean flags for isLoading, isError, isRetrying create 2^N combinations, most invalid.
Solution
Model states and transitions explicitly. Only allow defined transitions. Reject invalid ones. Libraries: XState (JS), statecharts. Even without a library, a switch on state with explicit transitions prevents bugs.
Code Snippets
Explicit state machine with transitions
type State = 'idle' | 'loading' | 'success' | 'error' | 'retrying';
type Event = 'FETCH' | 'SUCCESS' | 'ERROR' | 'RETRY' | 'RESET';
const transitions: Record<State, Partial<Record<Event, State>>> = {
idle: { FETCH: 'loading' },
loading: { SUCCESS: 'success', ERROR: 'error' },
success: { FETCH: 'loading', RESET: 'idle' },
error: { RETRY: 'retrying', RESET: 'idle' },
retrying: { SUCCESS: 'success', ERROR: 'error' },
};
function transition(state: State, event: Event): State {
const next = transitions[state]?.[event];
if (!next) throw new Error(`Invalid: ${state} + ${event}`);
return next;
}
// Usage
let state: State = 'idle';
state = transition(state, 'FETCH'); // 'loading'
state = transition(state, 'ERROR'); // 'error'
state = transition(state, 'RETRY'); // 'retrying'
// transition(state, 'FETCH') -- throws! Can't FETCH while retryingRevisions (0)
No revisions yet.