Состояния¶
Состояние (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— предыдущее состояниеStatemeta— любая статичная метаинформация, определенная в свойстве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. В противном случае вы создадите огромный связанный список и заново изобретете блокчейн, чего мы не собираемся делать.- Это поведение может быть изменено в будущих версиях.