All questions

Finite State Machine

Premium

Finite State Machine

"Loading spinner still showing after an error", "submit fires twice", "back button lands in an impossible screen" — most UI bugs are really state bugs: the app drifted into a combination you never intended. A finite state machine kills that whole class by making the legal states and the transitions between them explicit data. You're in exactly one state; an event either has a defined transition out of it or it's ignored. Libraries like XState are built on this; here you'll write the tiny interpreter at its heart.

Implement finiteStateMachine(config) returning a machine with send, can, matches, and subscribe, supporting guards and entry actions. See statecharts.dev.

Signature

function finiteStateMachine(config) {
  return { state, context, send, can, matches, subscribe };
}

Examples

const m = finiteStateMachine({
  initial: 'idle',
  context: { data: null },
  states: {
    idle: { on: { FETCH: 'loading' } },
    loading: {
      on: {
        SUCCESS: { target: 'ok', action: (ctx, e) => { ctx.data = e.data; } },
        ERROR:   { target: 'fail', guard: (ctx, e) => e.fatal === true },
      },
    },
    ok: {}, fail: {},
  },
});

m.send('FETCH');                     // -> 'loading'
m.send({ type: 'SUCCESS', data: 7 }); // -> 'ok', ctx.data === 7

Notes

  • A transition is a lookup — for the current state, find on[event.type]. No entry → ignore the event (stay put). Events are strings or { type, ...payload }.
  • Guards gate transitions — if a transition has a guard, it fires only when guard(context, event) is truthy; otherwise the machine stays.
  • Actions and entry — a transition's action runs during the switch; the target state's entry runs on arrival. The initial state's entry runs once at creation.
  • can, matches, subscribecan(event) previews whether a transition would fire; matches(state) checks the current state; subscribe notifies on each real transition.

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium