События¶
Событие (event) — это то, что заставляет конечный автомат переходить из текущего состояния в следующее состояние.
API¶
Событие — это объект со свойством type
, указывающим, к какому типу оно относится:
const timerEvent = {
type: 'TIMER', // the convention is to use CONST_CASE for event names
};
В XState события, которые имеют только type
, могут быть представлены только их строковым типом, как сокращение:
// equivalent to { type: 'TIMER' }
const timerEvent = 'TIMER';
Объекты событий также могут иметь другие свойства, которые представляют данные, связанные с событием:
const keyDownEvent = {
type: 'keydown',
key: 'Enter',
};
Отправка событий¶
Переход определяет, каким будет следующее состояние, учитывая текущее состояние и событие, определенные в его свойстве on: {...}
. Это можно увидеть, передав событие в метод перехода:
import { createMachine } from 'xstate';
const lightMachine = createMachine({
/* ... */
});
const { initialState } = lightMachine;
let nextState = lightMachine.transition(
initialState,
'TIMER'
); // string event
console.log(nextState.value);
// => 'yellow'
nextState = lightMachine.transition(nextState, {
type: 'TIMER',
}); // event object
console.log(nextState.value);
// => 'red'
Многие нативные события, такие как события DOM, совместимы и могут использоваться напрямую с XState, указав тип события в свойстве type
:
import { createMachine, interpret } from 'xstate';
const mouseMachine = createMachine({
on: {
mousemove: {
actions: [
(context, event) => {
const { offsetX, offsetY } = event;
console.log({ offsetX, offsetY });
},
],
},
},
});
const mouseService = interpret(mouseMachine).start();
window.addEventListener('mousemove', (event) => {
// event can be sent directly to service
mouseService.send(event);
});
Нулевые события¶
Внимание
Синтаксис нулевого события ({on: {'': ...}})
будет устаревшим в версии 5. Вместо него следует использовать новый синтаксис always
.
Нулевое событие (null event) — это событие, которое не имеет типа и происходит сразу после входа в состояние. В переходах оно представлено пустой строкой (''
):
// contrived example
const skipMachine = createMachine({
id: 'skip',
initial: 'one',
states: {
one: {
on: { CLICK: 'two' },
},
two: {
// null event '' always occurs once state is entered
// immediately take the transition to 'three'
on: { '': 'three' },
},
three: {
type: 'final',
},
},
});
const { initialState } = skipMachine;
const nextState = skipMachine.transition(
initialState,
'CLICK'
);
console.log(nextState.value);
// => 'three'
Существует много вариантов использования нулевых событий, особенно при определении переходов, когда (потенциально проходное) состояние сразу определяет, какое следующее состояние должно быть основано на защитных функциях:
const isAdult = ({ age }) => age >= 18;
const isMinor = ({ age }) => age < 18;
const ageMachine = createMachine({
id: 'age',
context: { age: undefined }, // age unknown
initial: 'unknown',
states: {
unknown: {
on: {
// immediately take transition that satisfies conditional guard.
// otherwise, no transition occurs
'': [
{ target: 'adult', cond: isAdult },
{ target: 'child', cond: isMinor },
],
},
},
adult: { type: 'final' },
child: { type: 'final' },
},
});
console.log(ageMachine.initialState.value);
// => 'unknown'
const personData = { age: 28 };
const personMachine = ageMachine.withContext(personData);
console.log(personMachine.initialState.value);
// => 'adult'