Конечные автоматы¶
Конечный автомат (state machine) — это конечный набор состояний, которые могут детерминированно переходить друг в друга из-за событий.
Конфигурация¶
И конечные автоматы, и диаграммы состояний определяются с помощью фабричной функции createMachine()
:
import { createMachine } from 'xstate';
const lightMachine = createMachine({
// Machine identifier
id: 'light',
// Initial state
initial: 'green',
// Local context for entire machine
context: {
elapsed: 0,
direction: 'east',
},
// State definitions
states: {
green: {
/* ... */
},
yellow: {
/* ... */
},
red: {
/* ... */
},
},
});
Конфигурация машины такая же, как конфигурация узла состояния, с добавлением свойства контекста:
context
— представляет локальное «расширенное состояние» для всех вложенных состояний машины. См. контекст для получения более подробной информации.
Параметры¶
Реализации для действий, активностей, задержек, защитных функций и служб могут быть указаны в конфигурации машины в виде строки, а затем указаны как объект во втором аргументе createMachine()
:
const lightMachine = createMachine(
{
id: 'light',
initial: 'green',
states: {
green: {
// ссылка на действие в виде строки
entry: 'alertGreen',
},
},
},
{
actions: {
// реализация действия
alertGreen: (context, event) => {
alert('Green!');
},
},
activities: {
/* ... */
},
delays: {
/* ... */
},
guards: {
/* ... */
},
services: {
/* ... */
},
}
);
У этого объекта есть 5 необязательных свойств:
actions
— сопоставление действий с их реализациейactivities
— сопоставление активностей с их реализациейdelays
— сопоставление задержек с их реализациейguards
— сопоставление охранников переходов с их реализациейservices
— сопоставление служб с их реализацией
Расширение автомата¶
Существующие автоматы могут быть расширены с помощью метода .withConfig()
, который принимает ту же структуру объекта, что и выше:
const lightMachine = // (same as above example)
const noAlertLightMachine = lightMachine.withConfig({
actions: {
alertGreen: (context, event) => {
console.log('green');
}
}
});
Начальный контекст¶
Как показано в первом примере, контекст определяется непосредственно в самой конфигурации. Если вы хотите расширить существующую машину с другим начальным контекстом, вы можете использовать .withContext()
и передать свой context
:
const lightMachine = // (same as first example)
const testLightMachine = lightMachine.withContext({
elapsed: 1000,
direction: 'north'
});
Внимание
Это не приведет к слиянию с исходным контекстом, а заменит исходный контекст контекстом, предоставленным для .withContext(...)
. Вы все еще можете «объединить» контексты вручную, указав machine.context
:
const testLightMachine = lightMachine.withContext({
// merge with original context
...lightMachine.context,
elapsed: 1000,
});