State Machines
The Finite State Machine (FSM) pattern is:
const { getState, send } = fsm(states, transitions, initialState)
States
States can be any type, usually extending string
or object
.
Factory Machines use state factory functions to create keyed state objects.
defineStates
Use defineStates
to create a fully-typed state factory.
const states = defineStates({
Idle: null,
Fetching: (userId: string) => ({ userId }),
Succeeded: (result: User) => ({ result }),
Failed: (error: Error) => ({ error })
})
key
and data
const state = states.Fetching('user-id')
state.key === 'Fetching'
state.data.userId === 'user-id'
match
console.log(state.match({
Idle: () => 'idle',
Fetching: ({ userId }) => `fetching ${userId}`,
Succeeded: ({ result }) => `succeeded ${result}`,
Failed: ({ error }) => `failed ${error}`
}))
Transitions
Transitions are keyed by state key
and transition type
.
From the state-machine
resolve function:
const to = machine.transitions[ev.from.key][ev.type];
Transition configuration varies by machine type.
- Basic state machine
transitions
will be used as the next state - Factory machines
transitions
can be string state keys or functions that return the next state - Promise machines
transitions
are already provided
Factory Machines
Create a factory machine with
createFactoryMachine(states, transitions, initialState)
Factory Machine States
Define states first with defineStates
or create inline by passing in creator map.
With inline states factory:
const machine = createFactoryMachine(
{
Idle: undefined,
Foo: (foo: string) => ({ foo }),
Bar: (bar: number) => ({ bar })
},
transitions,
'Idle'
)
With standalone states factory:
const states = defineStates( {
Idle: undefined,
Foo: (foo: string) => ({ foo }),
Bar: (bar: number) => ({ bar })
})
const machine = createFactoryMachine(
states,
transitions,
states.Foo(...)
)
Factory Machine Transitions
Factory Machine Transition values can be:
- a Factory State
key
- a function returning a Factory State
- a function returning a Resolver
A simple transition function:
(...myParameters: any[]) => MyExitState
A transition resolver function:
(...myParameters: any[]) => ({ type, from }) => MyExitState
For example, in the snippet below:
toggle
uses a simple statekey
foo
takes a parameter and returns a Factory Stateincrement
takes abar
parameter and returns a Resolver that incrementsev.from.data.bar
by that amount
const machine = createFactoryMachine(
states,
{
Idle: {
toggle: 'Foo'
},
Foo: {
toggle: 'Bar',
foo: (foo = 'foo') => states.Foo(`my-${foo}`),
},
Bar: {
toggle: 'Foo',
increment: (bar: number) => (ev) =>
states.Bar(ev.from.data.bar + bar)
}
},
'Idle'
)
Matchina types resolve this to:
Loading...