Перейти к содержанию

Начнём

Наш первый конечный автомат

Предположим, мы хотим смоделировать Promise как конечный автомат. Сначала установите XState с помощью NPM или Yarn:

npm install xstate --save

Если вы используете VSCode, вам следует установить наше расширение VSCode, чтобы вы могли визуализировать автомат, который вы строите, в процессе работы.

Затем в своем проекте импортируйте createMachine — функцию, которая создает конечный автомат.

import { createMachine } from 'xstate';

const promiseMachine = createMachine(/* ... */);

Мы передадим конфигурацию автомата createMachine. Нам потребуется предоставить:

  • id — для идентификации автомата
  • initial — для указания узла начального состояния, в котором должен находиться этот автомат
  • states — для определения каждого из дочерних состояний:
import { createMachine } from 'xstate';

const promiseMachine = createMachine({
  id: 'promise',
  initial: 'pending',
  states: {
    pending: {},
    resolved: {},
    rejected: {},
  },
});

Затем нам нужно добавить переходы к узлам состояния.

import { createMachine } from 'xstate';

const promiseMachine = createMachine({
  id: 'promise',
  initial: 'pending',
  states: {
    pending: {
      on: {
        RESOLVE: { target: 'resolved' },
        REJECT: { target: 'rejected' },
      },
    },
    resolved: {},
    rejected: {},
  },
});

Нам также нужно пометить узлы состояния resolved и rejected, как узлы конечного состояния, поскольку автомат Promise прекращает работу, как только достигает этих состояний:

import { createMachine } from 'xstate';

const promiseMachine = createMachine({
  id: 'promise',
  initial: 'pending',
  states: {
    pending: {
      on: {
        RESOLVE: { target: 'resolved' },
        REJECT: { target: 'rejected' },
      },
    },
    resolved: {
      type: 'final',
    },
    rejected: {
      type: 'final',
    },
  },
});

Теперь наш конечный автомат готов к визуализации. Вы можете скопировать / вставить приведенный выше код и визуализировать его в Stately Viz. Вот как это будет выглядеть:

Запуск нашего автомата

То, как мы запускаем наш автомат, зависит от того, где мы планируем его использовать.

В Node.js или Vanilla JS

Чтобы интерпретировать автомат и заставить его работать, нам нужно добавить интерпретатор. Этот код создает службу:

import { createMachine, interpret } from 'xstate';

const promiseMachine = createMachine({
  /* ... */
});

const promiseService = interpret(
  promiseMachine
).onTransition((state) => console.log(state.value));

// Start the service
promiseService.start();
// => 'pending'

promiseService.send({ type: 'RESOLVE' });
// => 'resolved'

В React

Если бы мы хотели использовать наш автомат внутри компонента React, мы могли бы использовать хук useMachine:

Дополнительно нам нужно установить пакет @xstate/react

import { useMachine } from '@xstate/react';

const Component = () => {
  const [state, send] = useMachine(promiseMachine);

  return (
    <div>
      {/** You can listen to what state the service is in */}
      {state.matches('pending') && <p>Loading...</p>}
      {state.matches('rejected') && <p>Promise Rejected</p>}
      {state.matches('resolved') && <p>Promise Resolved</p>}
      <div>
        {/** You can send events to the running service */}
        <button onClick={() => send('RESOLVE')}>
          Resolve
        </button>
        <button onClick={() => send('REJECT')}>
          Reject
        </button>
      </div>
    </div>
  );
};