Advanced transitions
Parent and child states offer more opportunities for various types of transitions. You can transition from any state to any other state. XState has a few different syntaxes to help you out.
Transitioning to a node’s own children​
Use the .target
syntax to transition to a child state from a parent state.
The following machine uses the .target
syntax for .hovered
:
import { createMachine } from 'xstate';
const machine = createMachine({
initial: 'inactive',
on: {
HOVER: '.hovered',
},
states: {
inactive: {},
hovered: {},
visited: {},
},
});
Whichever state the machine is in, whenever it receives a HOVER
event, it’ll transition to the hovered
state.
Transitioning to another node’s children​
Transition directly into a node’s children using the a.b
syntax.
The following machine uses the a.b
syntax for .hovered
:
import { createMachine } from 'xstate';
const machine = createMachine({
initial: 'inactive',
states: {
inactive: {
on: {
HOVER: 'active.hovered',
},
},
active: {
initial: 'focused',
states: {
focused: {},
hovered: {},
},
},
},
});
In the example above, the machine transitions directly to active.hovered
when the HOVER
event is received in state inactive
.
The initial
state of focused
inside active
is ignored.
Transitioning to any node​
If you want to transition to any state:
- Give the state node an
id
, for example,myState
- Target the state node with a
#
prefix:#myState
The approach above works for transitioning to any state node from any state node, so it’s a useful trick if you can’t target a state with the .a
or a.b
syntaxes.
The example below shows the paused
state with an id
of playerPaused
and that id
targeted using #playerPaused
:
import { createMachine } from 'xstate';
const musicMachine = createMachine({
initial: 'playing',
states: {
playing: {
initial: 'playingTrackOne',
states: {
playingTrackOne: {
on: {
PAUSE: {
target: '#playerPaused',
},
},
},
},
},
paused: {
id: 'playerPaused',
},
},
});
You can also give the root of your machine an id
and combine the use of the root machine’s id
with the a.b
syntax.
The example below shows the machine’s root with an id
of player
and the paused
state targeted using #player.paused
:
import { createMachine } from 'xstate';
const musicMachine = createMachine({
id: 'player',
initial: 'playing',
states: {
playing: {
initial: 'playingTrackOne',
states: {
playingTrackOne: {
on: {
PAUSE: {
target: '#player.paused',
},
},
},
},
},
paused: {},
},
});
Combining a machine’s root id
with the use of the a.b
syntax can help you reduce the number of state id
s required.