Parallel states
In statecharts, a parallel state is a state that has multiple child states (also known as regions) that are all active at the same time. This is different from a parent state, where only one child state is active at a time.
Parallel states have the following characteristics:
- Entering a parallel state will also simultaneously enter all of its regions.
- Exiting a parallel state will also simultaneously exit all of its regions.
- An event received in a parallel state is simultaneously received & handled by all of its regions.
Here is a music player example with a parallel state consisting of two regions, one for handling playing the track and one for handling the volume:
import { createMachine, assign } from 'xstate';
const playerMachine = createMachine({
id: 'player',
type: 'parallel',
states: {
track: {
initial: 'paused',
states: {
paused: {
on: { PLAY: 'playing' },
},
playing: {
on: { STOP: 'paused' },
},
},
},
volume: {
initial: 'normal',
states: {
normal: {
on: { MUTE: 'muted' },
},
muted: {
on: { UNMUTE: 'normal' },
},
},
},
},
});
Parallel state value​
The state value of a parallel state is an object with the state values of each of its regions.
const playerActor = createActor(playerMachine);
playerActor.start();
console.log(playerActor.getSnapshot().value);
// logs the object:
// {
// track: 'paused',
// volume: 'normal'
// }
Parallel onDone transition​
When all regions of a parallel state have reached their final states, the onDone
transition of the parallel state is taken.
In this example, the onDone
transition of the parallel state is taken when both regions have reached their final states; that is, when 'grindingBeans'
reaches the 'grindingBeans.beansGround'
state and 'boilingWater'
reaches the 'boilingWater.waterBoiled'
state.
import { createMachine } from 'xstate';
export const machine = createMachine({
id: 'coffee',
initial: 'preparing',
states: {
preparing: {
states: {
grindBeans: {
initial: 'grindingBeans',
states: {
grindingBeans: {
on: {
BEANS_GROUND: {
target: 'beansGround',
},
},
},
beansGround: {
type: 'final',
},
},
},
boilWater: {
initial: 'boilingWater',
states: {
boilingWater: {
on: {
WATER_BOILED: {
target: 'waterBoiled',
},
},
},
waterBoiled: {
type: 'final',
},
},
},
},
type: 'parallel',
onDone: {
target: 'makingCoffee',
},
},
makingCoffee: {},
},
});
Modeling​
Coming soon
- Avoid transitions between regions
- Used for separation of concerns that may affect each other (i.e. synchronization)
- If completely separate, prefer
invoke
instead
Parallel states cheatsheet​
Cheatsheet: create a parallel state​
import { createMachine } from 'xstate';
const machine = createMachine({
// ...
states: {
type: 'parallel',
states: {
one: {
/* ... */
},
two: {
/* ... */
},
three: {
/* ... */
},
},
onDone: {
// Taken when all regions have reached their final states
},
},
});