πŸ€– Robot

Fast 1kB functional library for creating Finite State Machines

Statecharts support hierarchial states (or nested states) as a way to deal with the state explosion problem of traditional finite state machines.

An example of a nested state machine is a crosswalk light. You give the βœ‹ when the stoplight is Yellow or Green. When the stoplight turns Red the crosswalk toggles to πŸšΆβ€β™€οΈ. The crosswalk light is a nested state machine of the parent stoplight.

In Robot nested state machines are represented as separate machines with invoke used to enter the child machine.

import { createMachine, invoke, state, transition, state as final } from 'robot3';

const stopwalk = createMachine({
walk: state(
transition('toggle', 'dontWalk')
),
dontWalk: final()
});

const stoplight = createMachine({
green: state(
transition('next', 'yellow')
),
yellow: state(
transition('next', 'red')
),
red: invoke(stopwalk,
transition('done', 'green')
)
});

You can transition through these states like so:

let service = interpret(stoplight, () => {});

service.send('next');
console.log(service.machine.current); // yellow

service.send('next');
console.log(service.machine.current); // red

let child = service.child;
console.log(child.machine.current); // walk

child.send('toggle');
console.log(child.machine.current); // dontWalk
console.log(service.machine.current); // green

service.send('next');
console.log(service.machine.current); // yellow

service.send('next');
console.log(service.machine.current); // red

child = service.child;
console.log(child.machine.current); // walk

child.send('toggle');
console.log(child.machine.current); // dontWalk
console.log(service.machine.current); // green

Since nested states is a useful feature of state machines you might want to simplify how to define substates. Thanks to Robot's composition properties it's easy to create a way declaratively define substates as part of a machine.

Here we create a nested function that defines a submachine.

// A helper function for more easily building nested state machines.
const nested = (to, states) => createMachine(states,
transition('done', to)
);

const stoplight = createMachine({
green: state(
transition('next', 'yellow')
),
yellow: state(
transition('next', 'red')
),
red: nested('green', {
walk: state(
transition('toggle', 'dontWalk')
),
dontWalk: final()
})
});