Иерархические узлы состояния¶
В диаграммах состояний состояния могут быть вложены в другие состояния. Эти вложенные состояния называются составными состояниями (compound states).
API¶
Следующий пример — конечный автомат светофора с вложенными состояниями:
const pedestrianStates = {
initial: 'walk',
states: {
walk: {
on: {
PED_COUNTDOWN: { target: 'wait' },
},
},
wait: {
on: {
PED_COUNTDOWN: { target: 'stop' },
},
},
stop: {},
blinking: {},
},
};
const lightMachine = createMachine({
key: 'light',
initial: 'green',
states: {
green: {
on: {
TIMER: { target: 'yellow' },
},
},
yellow: {
on: {
TIMER: { target: 'red' },
},
},
red: {
on: {
TIMER: { target: 'green' },
},
...pedestrianStates,
},
},
on: {
POWER_OUTAGE: { target: '.red.blinking' },
POWER_RESTORED: { target: '.red' },
},
});
'green'
и 'yellow'
состояния — это простые состояния (simple states) — у них нет дочерних состояний. Напротив, 'red'
состояние является составным состоянием (compound state), поскольку оно состоит из подсостояний (substates) pedestrianStates
.
Начальные состояния¶
Когда вводится составное состояние, сразу же вводится и его начальное состояние. В следующем примере светофора:
- переход в состояние
'red'
- поскольку
'red'
имеет начальное состояние'walk'
, то переходим в состояние{ red: 'walk' }
.
console.log(
lightMachine.transition('yellow', { type: 'TIMER' }).value
);
// => {
// red: 'walk'
// }
События¶
Когда простое состояние не обрабатывает event
, это event
распространяется до своего родительского состояния для обработки. В следующем примере светофора:
- состояние
{red: 'stop'}
не обрабатывает событие'TIMER'
- событие
'TIMER'
отправляется в'red'
родительское состояние, которое обрабатывает событие.
console.log(
lightMachine.transition(
{ red: 'stop' },
{ type: 'TIMER' }
).value
);
// => 'green'
Если ни состояние, ни какое-либо из его предков (родительских) состояний не обрабатывают событие, переход не происходит. В strict
режиме (указанном в конфигурации автомата) это вызовет ошибку.
console.log(
lightMachine.transition('green', { type: 'UNKNOWN' })
.value
);
// => 'green'