State(状态)
状态描述了机器的状态或模式,可以像暂停和播放一样简单。状态机一次只能处于一种状态。
这些状态是“有限的”;机器只能在您预定义的状态之间移动。
状态对象
状态对象表示正在运行的机器(actor)的当前状态,并包含以下属性:
value
:当前状态值,可以是:- 表示简单状态的字符串,例如
'playing'
,或: - 表示嵌套状态的对象,例如
{ paused: 'buffering' }
。
- 表示简单状态的字符串,例如
context
:当前的上下文(扩展状态)。meta
:包含状态节点元数据的对象。
const feedbackMachine = createMachine({
id: 'feedback',
initial: 'question',
context: {
feedback: '',
},
states: {
question: {
meta: {
question: 'How was your experience?',
},
},
},
});
const actor = createActor(feedbackMachine);
actor.start();
console.log(actor.getSnapshot());
// 记录包含以下内容的对象:
// {
// value: 'question',
// context: {
// feedback: ''
// },
// meta: {
// 'feedback.question': {
// question: 'How was your experience?'
// }
// }
// }
访问状态快照
您可以通过订阅 actor 或读取 actor 的 .getSnapshot()
方法来访问 actor 发出的状态(或 快照)。
const actor = createActor(feedbackMachine);
actor.subscribe((snapshot) => {
console.log(snapshot);
// logs the current snapshot state, e.g.:
// { value: 'question', ... }
// { value: 'thanks', ... }
});
actor.start();
console.log(actor.getSnapshot());
// logs { value: 'question', ... }
状态值
具有嵌套状态(或_状态图_)的状态机是一个树状结构,其中每个节点都是一个_状态节点_。根状态节点是表示整个机器的顶级状态节点。根节点可以有子状态节点,子状态节点也可以有子状态节点,依此类推。
状态值是一个表示机器中所有活动状态节点的对象。对于没有子状态节点的状态机,状态值是一个字符串:
即将推出…一个视觉示例。
state.value === 'question'
state.value === 'thanks'
state.value === 'closed'
对于具有父状态节点的状态机,状态值是一个对象:
即将推出…一个视觉示例。
state.value === { form: 'invalid' }
- 这表示一个状态机,其活动子节点的键为form
,且其活动子节点的键为invalid
对于具有并行状态节点的状态机,状态值包含具有多个键的对象,每个键表示一个状态节点区域:
state.value ===
{
monitor: 'on',
mode: 'dark',
};
状态机也可能只有根状态节点而没有其他状态节点。对于这些状态机,状态值为 null
。
状态上下文
状态机可以具有上下文,这是一个表示机器扩展状态的对象。上下文是不可变的,只能通过在动作中分配来更新。您可以读取 state.context
属性以获取当前上下文。
const currentState = feedbackActor.getSnapshot();
console.log(currentState.context);
// logs { feedback: '' }
- 如果在机器配置中未指定上下文,则对象为空
{}
(默认) - 切勿修改此对象;应将其视为不可变/只读
状态子节点
state.children
属性表示当前状态中所有已生成/调用的 actor。它是一个对象,其中键表示 actor 的 ID,值表示 ActorRef
实例。
- 这是您通过 ID 访问生成/调用的 actor 的地方
- 这就是为什么您应该为生成/调用的 actor 分配 ID
- 停止的 actor 不会出现在这里
state.can(eventType)
state.can(event)
方法确定如果将 event
对象发送到机器 actor 是否会导致状态更改。如果由于发送 event
导致状态更改,则该方法将返回 true
;否则返回 false
:
const feedbackMachine = createMachine({
// ...
states: {
form: {
// ...
on: {
'feedback.submit': {
guard: 'isValid',
target: 'thanks',
},
},
},
},
});
const feedbackActor = createActor(feedbackMachine).start();
// ...
const currentState = feedbackActor.getSnapshot();
console.log(currentState.can({ type: 'feedback.submit' }));
// 如果 'feedback.submit' 事件会导致状态转换,则记录 `true`,这将在以下情况下发生:
// - 当前状态是 'form'
// - 'isValid' 守卫评估为 `true`
状态被认为是“已更 改”,如果给定的 state
和 event
对象启用了转换。
state.hasTag(tag)
state.hasTag(tag)
方法确定当前状态值中的任何状态节点是否具有给定的 tag
。这对于确定状态是否为特定状态,或状态是否属于特定状态组非常有用。
const feedbackMachine = createMachine({
// ...
states: {
submitting: {
tags: ['loading'],
// ...
},
},
});
const feedbackActor = createActor(feedbackMachine).start();
const currentState = feedbackActor.getSnapshot();
const showLoadingSpinner = currentState.hasTag('loading');
优先使用 state.hasTag(tag)
而不是 state.matches(stateValue)
,因为 state.hasTag(tag)
对机器的更改更具弹性。
state.matches(stateValue)
state.matches(stateValue)
方法确定当前 state.value
是否与给定的 stateValue
匹配。如果当前 state.value
是所提供 stateValue
的“子集”,则该方法将返回 true
。
// state.value === 'question'
state.matches('question'); // true
// state.value === { form: 'invalid' }
state.matches('form'); // true
state.matches('question'); // false
state.matches({ form: 'invalid' }); // true
state.matches({ form: 'valid' }); // false
// state.value === { 'form submitting' : 'invalid value' }
state.matches('form submitting'); // true
state.matches('form'); // false
state.matches({ 'form submitting' : 'invalid value' }); // true
state.matches({ 'form submitting' : 'value' }); // false
state.output
state.output
属性表示状态机在其顶级最终状态时的输出数据;即 state.status === 'done'
。
const state = actor.getSnapshot();
if (state.status === 'done') {
console.log(state.output);
}
state.getMeta()
state.getMeta()
方法表示 state
中所有状态节点的元数据。它是一个对象,其中键表示状态节点的 ID,值是该状态节点的元数据。
const feedbackMachine = createMachine({
id: 'feedback',
// ...
states: {
form: {
meta: {
view: 'shortForm',
}
}
}
});
const feedbackActor = createActor(feedbackMachine).start();
// 假设当前状态是 'form'
const currentState = feedbackActor.getSnapshot();
console.log(currentState.getMeta());
// 记录 { 'feedback.form': { view:'shortForm' } }
状态描述
您可以将 .description
添加到状态中,以描述其目的并与您的团队共享相关的注释。在 Stately Studio 的编辑器中,这些描述会在机器中呈现,并支持包括链接、图像和列表在内的 markdown。 阅读更多关于 Stately Studio 中的描述。
states: {
"Loading Move Destinations": {
description:
"Load data from the server based on the entity's id and type (project or machine). Result includes the entity's current location, and the list or tree of valid destination options to which the user may move that entity.",
invoke: {
src: "loadMoveData",
id: "loadMoveData",
onDone: [
{
target: "Destination Menu",
actions: "setDestinations",
},
],
onError: [
{
target: "Data Loading Error",
},
],
},
},
}
状态和 TypeScript
即将推出
状态速查表
速查表:读取或匹配状态值
const state = actor.getSnapshot();
const currentStateValue = state.value;
const isLoading = state.matches('loading');
速查表:读取状态上下文
console.log(state.context);
速查表:读取状态输出
if (state.status === 'done') {
// 输出可能存在
console.log(state.output);
} else {
// 输出不存在
state.output === undefined;
}
state.output === undefined;
}
速查表:读取状态元数据
console.log(state.getMeta());