Sikau

React patterns at scale · Day 6 · about 35 min

Reducers as state machines

Make impossible states impossible.

Loading, failed and successful — all at once

A checkout button tracks its request with booleans: isLoading, isError, isSuccess. Three booleans make eight combinations, and only four make sense. Sooner or later a bug produces the others: a spinner *and* an error, or a success message while the second click is still sending a duplicate order to the kitchen.

The field guide recommends useReducer once updates get complex, because every change becomes a named action handled in one place. Push that one step further and the reducer becomes a finite state machine: one status that can only be one thing at a time, and a table of which events are allowed in which status. Impossible states stop being bugs you test for — they can't be represented at all.

States, events and a transition table

A reducer is a pure function (state, action) => newState. As a state machine it first asks: *is this event allowed in the current status?* If not, it returns the same state object, and React skips the re-render. The allowed moves live in a plain object you can read at a glance — or draw as a diagram for your team.

const MACHINE = {
  idle: { SUBMIT: "submitting" },
  submitting: { RESOLVE: "success", REJECT: "failure" },
  failure: { RETRY: "submitting", CANCEL: "idle" },
  success: { RESET: "idle" },
};

function orderReducer(state, event) {
  const next = MACHINE[state.status][event.type];
  if (!next) return state;
  // …build the next state for this event
}

A traffic light: A light is red, amber or green — never two at once — and it only moves in a fixed order. No button press makes it jump from red to 'green and red'. A state machine gives your UI the same guarantee.

The rest of this lesson

  • Let the state drive the effectsexplain
  • A second clickpredict
  • Read the machinematch
  • Ignore what isn't allowedfill
  • A checkout machinewrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 10 lessons of React patterns at scale