Состояния¶
Состояние (state) — это абстрактное представление системы (например, приложения) в определенный момент времени.
API¶
Текущее состояние машины представлено экземпляром State
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Определение состояния¶
Экземпляр объекта State
является сериализуемым в формате JSON и имеет следующие свойства:
value
— текущее значение состояния (например,{red: 'walk'}
)context
— текущее значение контекста этого состоянияevent
— объект события, вызвавший переход в это состояниеactions
— массив действий, которые нужно выполнитьactivities
— отображение активностей вtrue
, если активность запущена или вfalse
, если остановлена.history
— предыдущее состояниеState
meta
— любая статичная метаинформация, определенная в свойствеmeta
узла состоянияdone
— признак конечного состояния
Объект State
также содержит другие свойства, такие как historyValue
, events
, tree
и другие, которые обычно не имеют отношения к делу и предназначены для внутреннего использования.
Методы и свойства состояния¶
Вот несколько полезных методов и свойств, которые можно использовать для улучшения процесса разработки:
state.matches()
¶
Метод state.matches(parentStateValue)
определяет, является ли текущее значение state.value
подмножеством заданного parentStateValue
. Метод определяет, «совпадает» ли значение родительского состояния со значением состояния. Например, если текущее значение state.value
равно {red: 'stop'}
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Подсказка
Если вы хотите сравнить одно из нескольких состояний, вы можете использовать .some()
для массива значений состояния, чтобы выполнить это:
1 2 3 4 |
|
state.nextEvents
¶
state.nextEvents
указывает следующие события, которые вызовут переход из текущего состояния:
1 2 3 4 |
|
state.nextEvents
полезен для определения, какие следующие события могут быть выполнены, и представления этих потенциальных событий в пользовательском интерфейсе, таких как включение или отключение определенных кнопок.
state.changed
¶
state.changed
указывает, изменилось ли это состояние по сравнению с предыдущим состоянием. Состояние считается «измененным», если:
- Его значение не равно его предыдущему значению, или:
- У него есть какие-либо новые действия (побочные эффекты) для выполнения.
Исходное состояние (без истории) вернет undefined
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
state.done
¶
state.done
указывает, является ли состояние «конечным состоянием» — это состояние, которое указывает, что его автомат достиг своего конечного (терминального) состояния и больше не может переходить в какое-либо другое состояние.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
state.toStrings()
¶
Метод state.toStrings()
возвращает массив строк, представляющих все пути значений состояния. Например, если текущее значение state.value
равно {red: 'stop'}
:
1 2 3 4 5 |
|
Метод state.toStrings()
полезен для представления текущего состояния в строковых средах, таких как классы CSS или атрибуты данных.
state.children
¶
state.children
— это объект, отображающий идентификаторы порожденных служб / акторов на их экземпляры. См. 📖 Referencing Services для более подробной информации.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
state.hasTag()
¶
Начиная с версии 4.19.0
Метод state.hasTag(tag)
определяет, есть ли в текущей конфигурации состояния узел состояния с данным тегом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Например, если указанный выше автомат находится в зеленом или желтом состоянии, вместо прямого сопоставления состояния с помощью state.matches('green') || state.matches('yellow')
, можно использовать state.hasTag('go')
:
1 2 |
|
state.can()
¶
Начиная с версии 4.25.0
Метод state.can(event)
определяет, вызовет ли событие изменение состояния, если оно будет отправлено на интерпретируемый автомат. Метод вернет истину, если состояние изменится из-за отправляемого события; иначе метод вернет false
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
Состояние считается «измененным», если state.changed
true
и если выполняется любое из следующих условий:
- значение
state.value
изменилось - есть новые
state.actions
, которые нужно выполнить - значение
state.context
изменилось
Сохранение состояния¶
Как уже упоминалось, объект State
можно сохранить, сериализовав его в строковый формат JSON:
1 2 3 4 5 6 7 8 |
|
Состояние можно восстановить с помощью статического метода State.create(...)
:
1 2 3 4 5 6 7 8 9 10 11 |
|
Затем вы можете интерпретировать автомат из этого состояния, передав State
в метод .start(...)
интерпретируемой службы:
1 2 3 4 |
|
Это также будет поддерживать и восстанавливать предыдущие состояния истории и гарантирует, что .events
и .nextEvents
представляют правильные значения.
Внимание
Сохранение созданных акторов еще не поддерживается в XState.
Метаданные состояния¶
Мета-данные, которые представляют собой статические данные, описывающие соответствующие свойства любого узла состояния, могут быть указаны в свойстве .meta
узла состояния:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
Текущее состояние машины собирает .meta
данные всех узлов состояния, представленные значением состояния, и помещает их в объект, где:
- Ключи — это идентификаторы узлов состояния.
- Значения — это значения мета-узла состояния
.meta
.
Например, если вышеуказанный автомат находится в состоянии failure.timeout
(которое представлено двумя узлами состояния с идентификаторами «failure
» и «failure.timeout
»), свойство .meta
объединит все значения .meta
следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Подсказка: Агрегирование метаданных
Что делать с метаданными — решать вам. В идеале метаданные должны содержать только значения, сериализуемые в формате JSON. Рассмотрите возможность слияния / агрегирования метаданных иначе. Например, следующая функция отбрасывает ключи идентификатора узла состояния (если они неактуальны) и объединяет метаданные:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Примечания¶
- Вам никогда не придется создавать экземпляр
State
вручную. СчитайтеState
объектом, доступным только для чтения, который поступает только отmachine.transition(...)
илиservice.onTransition(...)
. state.history
не сохраняет свою историю во избежание утечек памяти.state.history.history === undefined
. В противном случае вы создадите огромный связанный список и заново изобретете блокчейн, чего мы не собираемся делать.- Это поведение может быть изменено в будущих версиях.