# 状态节点
¥State Nodes
这些 XState v4 文档不再维护
XState v5 现已推出!阅读有关 XState v5 的更多信息 (opens new window) 和 查看 XState v5 文档 (opens new window)。
¥XState v5 is out now! Read more about XState v5 (opens new window) and check out the XState v5 docs (opens new window).
状态机包含状态节点(如下所述),它们共同描述机器可以处于的 整体状态 状态。在下一节描述的 fetchMachine
中,有状态节点,例如:
¥A state machine contains state nodes (explained below) that collectively describe the overall state a machine can be in. In the fetchMachine
described in the next section, there are state nodes, such as:
// ...
{
states: {
// state node
idle: {
on: {
FETCH: {
target: 'pending';
}
}
}
}
}
以及整体状态,即 machine.transition()
函数的返回值或者 service.onTransition()
的回调值:
¥And the overall state, which is the return value of the machine.transition()
function or the callback value of service.onTransition()
:
const nextState = fetchMachine.transition('pending', { type: 'FULFILL' });
// State {
// value: { success: 'items' },
// actions: [],
// context: undefined,
// ...
// }
# 什么是状态节点?
¥What Are State Nodes?
在 XState 中,状态节点指定状态配置。它们在机器的 states
属性上定义。同样,子状态节点是在状态节点的 states
属性上分层定义的。
¥In XState, a state node specifies a state configuration. They are defined on the machine's states
property. Likewise, sub-state nodes are hierarchically defined on the states
property of a state node.
从 machine.transition(state, event)
确定的状态代表状态节点的组合。例如,在下面的机器中,有一个 success
状态节点和一个 items
子状态节点。状态值 { success: 'items' }
代表这些状态节点的组合。
¥The state determined from machine.transition(state, event)
represents a combination of state nodes. For example, in the machine below, there's a success
state node and an items
substate node. The state value { success: 'items' }
represents the combination of those state nodes.
const fetchMachine = createMachine({
id: 'fetch',
// Initial state
initial: 'idle',
// States
states: {
idle: {
on: {
FETCH: { target: 'pending' }
}
},
pending: {
on: {
FULFILL: { target: 'success' },
REJECT: { target: 'failure' }
}
},
success: {
// Initial child state
initial: 'items',
// Child states
states: {
items: {
on: {
'ITEM.CLICK': { target: 'item' }
}
},
item: {
on: {
BACK: { target: 'items' }
}
}
}
},
failure: {
on: {
RETRY: { target: 'pending' }
}
}
}
});
# 状态节点类型
¥State Node Types
有五种不同类型的状态节点:
¥There are five different kinds of state nodes:
原子状态节点没有子状态。(即,它是叶节点。)
¥An atomic state node has no child states. (I.e., it is a leaf node.)
复合状态节点包含一个或多个子
states
,并具有initial
状态,该状态是这些子状态之一的关键。¥A compound state node contains one or more child
states
, and has aninitial
state, which is the key of one of those child states.并行状态节点包含两个或多个子
states
,并且没有初始状态,因为它表示同时处于其所有子状态。¥A parallel state node contains two or more child
states
, and has no initial state, since it represents being in all of its child states at the same time.最终状态节点是表示抽象 "terminal" 状态的叶节点。
¥A final state node is a leaf node that represents an abstract "terminal" state.
历史状态节点是一个抽象节点,表示解析其父节点的最新浅层或深层历史状态。
¥A history state node is an abstract node that represents resolving to its parent node's most recent shallow or deep history state.
状态节点类型可以在状态节点上显式定义:
¥The state node type can be explicitly defined on the state node:
const machine = createMachine({
id: 'fetch',
initial: 'idle',
states: {
idle: {
type: 'atomic',
on: {
FETCH: { target: 'pending' }
}
},
pending: {
type: 'parallel',
states: {
resource1: {
type: 'compound',
initial: 'pending',
states: {
pending: {
on: {
'FULFILL.resource1': { target: 'success' }
}
},
success: {
type: 'final'
}
}
},
resource2: {
type: 'compound',
initial: 'pending',
states: {
pending: {
on: {
'FULFILL.resource2': { target: 'success' }
}
},
success: {
type: 'final'
}
}
}
},
onDone: 'success'
},
success: {
type: 'compound',
initial: 'items',
states: {
items: {
on: {
'ITEM.CLICK': { target: 'item' }
}
},
item: {
on: {
BACK: { target: 'items' }
}
},
hist: {
type: 'history',
history: 'shallow'
}
}
}
}
});
将 type
显式指定为 'atomic'
、'compound'
、'parallel'
、'history'
或 'final'
对于 TypeScript 中的分析和类型检查很有帮助。然而,只有并行、历史和最终状态才需要它。
¥Explicitly specifying the type
as 'atomic'
, 'compound'
, 'parallel'
, 'history'
, or 'final'
is helpful with regard to analysis and type-checking in TypeScript. However, it is only required for parallel, history, and final states.
# 瞬态节点
¥Transient State Nodes
瞬态节点是 "pass-through" 状态节点,立即转换到另一个状态节点;也就是说,机器不会停留在瞬态状态。瞬态节点对于根据条件确定机器应该从先前状态真正转到哪个状态非常有用。它们与 UML 中的 选择伪状态 (opens new window) 最相似。
¥A transient state node is a "pass-through" state node that immediately transitions to another state node; that is, a machine does not stay in a transient state. Transient state nodes are useful for determining which state the machine should really go to from a previous state based on conditions. They are most similar to choice pseudostates (opens new window) in UML.
定义瞬态节点的最佳方法是作为无事件状态和 always
转换。这是一个转换,其中第一个条件为 true 时立即执行。
¥The best way to define a transient state node is as an eventless state, and an always
transition. This is a transition where the first condition that evaluates to true is immediately taken.
例如,该机器的初始瞬态状态解析为 'morning'
、'afternoon'
或 'evening'
,具体取决于时间(隐藏实现细节):
¥For example, this machine's initial transient state resolves to 'morning'
, 'afternoon'
, or 'evening'
, depending on what time it is (implementation details hidden):
const timeOfDayMachine = createMachine({
id: 'timeOfDay',
initial: 'unknown',
context: {
time: undefined
},
states: {
// Transient state
unknown: {
always: [
{ target: 'morning', cond: 'isBeforeNoon' },
{ target: 'afternoon', cond: 'isBeforeSix' },
{ target: 'evening' }
]
},
morning: {},
afternoon: {},
evening: {}
}
}, {
guards: {
isBeforeNoon: // ...
isBeforeSix: // ...
}
});
const timeOfDayService = interpret(timeOfDayMachine.withContext({ time: Date.now() }))
.onTransition(state => console.log(state.value))
.start();
// => 'morning' (assuming the time is before noon)
# 状态节点元数据
¥State Node Meta Data
元数据是描述任何 状态节点 相关属性的静态数据,可以在状态节点的 .meta
属性上指定:
¥Meta data, which is static data that describes relevant properties of any state node, can be specified on the .meta
property of the state node:
const fetchMachine = createMachine({
id: 'fetch',
initial: 'idle',
states: {
idle: {
on: {
FETCH: { target: 'loading' }
}
},
loading: {
after: {
3000: { target: 'failure.timeout' }
},
on: {
RESOLVE: { target: 'success' },
REJECT: { target: 'failure' },
TIMEOUT: { target: 'failure.timeout' } // manual timeout
},
meta: {
message: 'Loading...'
}
},
success: {
meta: {
message: 'The request succeeded!'
}
},
failure: {
initial: 'rejection',
states: {
rejection: {
meta: {
message: 'The request failed.'
}
},
timeout: {
meta: {
message: 'The request timed out.'
}
}
},
meta: {
alert: 'Uh oh.'
}
}
}
});
机器的当前状态收集由状态值表示的所有状态节点的 .meta
数据,并将它们放在一个对象上,其中:
¥The current state of the machine collects the .meta
data of all of the state nodes represented by the state value, and places them on an object where:
键是 状态节点 ID
¥The keys are the state node IDs
这些值为状态节点
.meta
值¥The values are the state node
.meta
values
有关用法和更多信息,请参阅 状态元数据。
¥See state meta data for usage and more information.
# 标签
¥Tags
状态节点可以有标签,这些标签是帮助描述状态节点的字符串术语。标签是元数据,可用于对不同状态节点进行分类。例如,你可以使用 "loading"
标记来表示哪些状态节点代表正在加载数据的状态,并确定状态是否包含带有 state.hasTag(tag)
标记的状态节点:
¥State nodes can have tags, which are string terms that help describe the state node. Tags are metadata that can be useful in categorizing different state nodes. For example, you can signify which state nodes represent states in which data is being loaded by using a "loading"
tag, and determine if a state contains those tagged state nodes with state.hasTag(tag)
:
const machine = createMachine({
initial: 'idle',
states: {
idle: {
on: {
FETCH: 'loadingUser'
}
},
loadingUser: {
tags: ['loading']
// ...
},
loadingFriends: {
tags: ['loading']
// ...
},
editing: {
// ...
}
}
});
machine.initialState.hasTag('loading');
// => false
machine.transition(machine.initialState, 'FETCH').hasTag('loading');
// => true