Skip to content

Параллельные состояния

Состояние может объявлять регионы parallel — набор независимых под-машин, которые все становятся активными при входе в родительское состояние и уничтожаются при выходе из него.

ts
const editor = defineMachine({
  id: 'editor',
  initial: 'editing',
  states: {
    editing: {
      parallel: {
        saving: {
          initial: 'idle',
          states: {
            idle: { on: { START_SAVE: { target: 'saving' } } },
            saving: { on: { SAVE_DONE: { target: 'saved' } } },
            saved: {},
          },
        },
        validation: {
          initial: 'valid',
          states: {
            valid: { on: { INVALIDATE: { target: 'invalid' } } },
            invalid: { on: { VALIDATE: { target: 'valid' } } },
          },
        },
      },
    },
    idle: {},
  },
})

send() доставляет каждое событие во все активные регионы. Каждый регион обрабатывает его независимо.

ts
const { matches, send } = useMachine(editor)

matches('editing') // основное состояние
matches({ saving: 'idle' }) // проверка региона
matches({ validation: 'valid' }) // другой регион

await send('INVALIDATE')
matches({ validation: 'invalid' }) // true
matches({ saving: 'idle' }) // всё ещё true — не затронуто

Разрешение конфликтов контекста: переход каждого региона сообщает только о полях, которые реально затронули его собственные actions — нетронутое поле никогда не перезаписывается устаревшей копией соседнего региона. Когда два региона действительно возвращают Partial<context>, затрагивающий одно и то же поле, побеждает последний регион в порядке объявления. В dev-режиме выводится console.warn с именами конфликтующих регионов и полем.

Ограничение: параллельные регионы поддерживают один уровень вложенности. Регионы не могут сами содержать parallel. Это осознанное решение для контроля сложности.