State machine advent: One event, two possible state transitions (15/24)
Mikey Stengel
Posted on December 15, 2019
Conditional logic is everywhere. While state machines reduce conditional logic by eliminating impossible states, there is some conditional logic we want to have within our machines. In particular, when one or the other action should be executed or multiple state transitions exist. We can define such conditional logic using the very concept we've learned yesterday, guards.
By providing an array of possible state transitions, the state transition with the first guard that evaluates to true will determine the next state of our machine. Let's say we want our thermostat to distinctively express whether it is cold or warm. If the temperature is below 18°C, it should go into the cold
state and above, transition to the warm
state.
import { Machine, assign } = 'xstate';
const thermostatMachine = Machine({
id: 'thermostat',
initial: 'inactive',
context: {
temperature: 20,
},
states: {
inactive: {
on: {
POWER_TOGGLE: 'active'
}
},
active: {
initial: 'warm',
states: {
cold: {},
warm: {},
},
on: {
POWER_TOGGLE: {
target: 'inactive',
},
SET_TEMPERATURE: [
{
target: '.cold',
cond: (context, event) => event.temperature < 18,
actions: assign({
temperature: (context, event) => event.temperature,
}),
},
{
// transition without a guard as a fallback.
target: '.warm',
actions: assign({
temperature: (context, event) => event.temperature,
}),
},
]
}
},
}
});
Think of the state transition array as a switch case to determine the next state of a machine. The default
transition can be expressed as a state transition without a guard as seen in the example above.
Notice how we had to duplicate the action to assign the temperature. Similar to when machines transition from one state to another, actions
are only executed if no guard is defined, or when a guard evaluates to true.
To give one more example of this behavior, the code below will never call the 'log' action.
[
{
target: 'cold',
cond: () => false,
actions: 'log',
},
{
target: 'warm',
},
]
Tomorrow we'll refactor the thermostatMachine
so that we don't have to define the same action twice.
About this series
Throughout the first 24 days of December, I'll publish a small blog post each day teaching you about the ins and outs of state machines and statecharts.
The first couple of days will be spend on the fundamentals before we'll progress to more advanced concepts.
Posted on December 15, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 16, 2024