# @xstate/graph
这些 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).
@xstate/graph package (opens new window) 包含 XState 机的图形算法和实用程序。
¥The @xstate/graph package (opens new window) contains graph algorithms and utilities for XState machines.
# 快速开始
¥Quick Start
安装
xstate
和@xstate/graph
:¥Install
xstate
and@xstate/graph
:
npm install xstate @xstate/graph
导入图形实用程序。示例:
¥Import the graph utilities. Example:
import { createMachine } from 'xstate';
import { getSimplePaths } from '@xstate/graph';
const machine = createMachine(/* ... */);
const paths = getSimplePaths(machine);
# API
# getShortestPaths(machine, options?)
参数
¥Arguments
machine
- 要遍历的Machine
(opens new window)¥
machine
- theMachine
(opens new window) to traverseoptions
(可选) - options 自定义算法如何遍历机器¥
options
(optional) - options that customize how the algorithm will traverse the machine
将 machine (opens new window) 的 最短路径(Dijkstra 算法) (opens new window) 从初始状态返回到每个其他状态作为映射对象,其中:
¥Returns the shortest paths (Dijkstra's algorithm) (opens new window) of a machine (opens new window) from the initial state to every other state as a mapped object, where the:
key 是字符串化状态
¥key is the stringified state
value 是一个具有以下属性的对象:
¥value is an object with the properties:
state
- 目标State
(opens new window)¥
state
- the targetState
(opens new window)path
- 从初始状态到目标状态的最短路径¥
path
- the shortest path to get from the initial state to the target state
path
是一个段数组,其中每个段都是一个具有以下属性的对象:
¥The path
is an array of segments, where each segment is an object with the properties:
state
- 该段的State
(opens new window)¥
state
- theState
(opens new window) of the segmentweight
- 路径总 weight (opens new window)¥
weight
- the total weight (opens new window) of the path目前,从一种状态到另一种状态的每次转换的权重均为 1。将来这将是可定制的。
¥Currently, each transition from one state to another has a weight of 1. This will be customizable in the future.
event
- 将machine
从路径中的状态转换到下一个状态的事件对象¥
event
- the event object that transitions themachine
from the state to the next state in the path
每条路径都从初始状态开始。
¥Every path starts with the initial state.
整体对象结构如下所示:
¥The overall object structure looks like this:
{
"<SERIALIZED STATE>": {
"state": State { ... },
"path": [
{
"state": State { ... },
"event": { "type": "<event.type>", "<PROP>": "<event.PROP>" }
},
{
"state": State { ... },
"event": { "type": "<event.type>", "<PROP>": "<event.PROP>" }
},
...
]
},
...
}
示例
¥Example
import { createMachine } from 'xstate';
import { getShortestPaths } from '@xstate/graph';
const feedbackMachine = createMachine({
id: 'feedback',
initial: 'question',
states: {
question: {
on: {
CLICK_GOOD: 'thanks',
CLICK_BAD: 'form',
CLOSE: 'closed',
ESC: 'closed'
}
},
form: {
on: {
SUBMIT: 'thanks',
CLOSE: 'closed',
ESC: 'closed'
}
},
thanks: {
on: {
CLOSE: 'closed',
ESC: 'closed'
}
},
closed: {
type: 'final'
}
}
});
const shortestPaths = getShortestPaths(feedbackMachine);
console.log(shortestPaths);
// => {
// '"question"': {
// state: State { value: 'question', context: undefined },
// weight: 0,
// path: []
// },
// '"thanks"': {
// state: State { value: 'thanks', context: undefined },
// weight: 1,
// path: [
// {
// state: State { value: 'question', context: undefined },
// event: { type: 'CLICK_GOOD' }
// }
// ]
// },
// '"form"': {
// state: State { value: 'form', context: undefined },
// weight: 1,
// path: [
// {
// state: State { value: 'question', context: undefined },
// event: { type: 'CLICK_BAD' }
// }
// ]
// },
// '"closed"': {
// state: State { value: 'closed', context: undefined },
// weight: 1,
// path: [
// {
// state: State { value: 'question', context: undefined },
// event: { type: 'CLOSE' }
// }
// ]
// }
// };
# getSimplePaths(machine, options?)
参数
¥Arguments
machine
- 要遍历的Machine
(opens new window)¥
machine
- theMachine
(opens new window) to traverseoptions
(可选) - options 自定义算法如何遍历机器¥
options
(optional) - options that customize how the algorithm will traverse the machine
返回 machine (opens new window) 的 简单的路径 (opens new window) 作为映射对象,其中:
¥Returns the simple paths (opens new window) of a machine (opens new window) as a mapped object, where the:
key 是字符串化状态
¥key is the stringified state
value 是一个具有以下属性的对象:
¥value is an object with the properties:
state
- 目标State
(opens new window)¥
state
- the targetState
(opens new window)paths
- 从初始状态到目标状态的路径数组¥
paths
- the array of paths to get from the initial state to the target state
paths
中的每个 path
都是一个段数组,其中路径的每个段都是一个具有以下属性的对象:
¥Each path
in paths
is an array of segments, where each segment of the path is an object with the properties:
state
- 该段的State
(opens new window)¥
state
- theState
(opens new window) of the segmentevent
- 将machine
从路径中的状态转换到下一个状态的事件对象¥
event
- the event object that transitions themachine
from the state to the next state in the path
每条路径都从初始状态开始。
¥Every path starts with the initial state.
整体对象结构如下所示:
¥The overall object structure looks like this:
{
"<SERIALIZED STATE>": {
"state": State { ... },
"paths": [
[
{
"state": State { ... },
"event": { "type": "<event.type>", "<PROP>": "<event.PROP>" }
},
{
"state": State { ... },
"event": { "type": "<event.type>", "<PROP>": "<event.PROP>" }
},
...
],
...
]
},
...
}
示例
¥Example
import { createMachine } from 'xstate';
import { getSimplePaths } from '@xstate/graph';
const feedbackMachine = createMachine({
id: 'feedback',
initial: 'question',
states: {
question: {
on: {
CLICK_GOOD: 'thanks',
CLICK_BAD: 'form',
CLOSE: 'closed',
ESC: 'closed'
}
},
form: {
on: {
SUBMIT: 'thanks',
CLOSE: 'closed',
ESC: 'closed'
}
},
thanks: {
on: {
CLOSE: 'closed',
ESC: 'closed'
}
},
closed: {
type: 'final'
}
}
});
const simplePaths = getSimplePaths(feedbackMachine);
console.log(simplePaths);
// => {
// '"question"': {
// state: { value: 'question', context: undefined },
// paths: [[]]
// },
// '"thanks"': {
// state: { value: 'thanks', context: undefined },
// paths: [
// [
// {
// state: { value: 'question', context: undefined },
// event: { type: 'CLICK_GOOD' }
// }
// ],
// [
// {
// state: { value: 'question', context: undefined },
// event: { type: 'CLICK_BAD' }
// },
// {
// state: { value: 'form', context: undefined },
// event: { type: 'SUBMIT' }
// }
// ]
// ]
// },
// '"closed"': {
// state: { value: 'closed', context: undefined },
// paths: [
// [
// {
// state: { value: 'question', context: undefined },
// event: { type: 'CLICK_GOOD' }
// },
// {
// state: { value: 'thanks', context: undefined },
// event: { type: 'CLOSE' }
// }
// ],
// [
// {
// state: { value: 'question', context: undefined },
// event: { type: 'CLICK_GOOD' }
// },
// {
// state: { value: 'thanks', context: undefined },
// event: { type: 'ESC' }
// }
// ],
// ...
// ]
// },
// ...
// };
# getPathFromEvents(machine, events)
参数
¥Arguments
machine
- 要遍历的Machine
(opens new window)¥
machine
- theMachine
(opens new window) to traverseevents
- 生成路径的事件序列¥
events
- the sequence of events to generate a path from
返回具有以下键的路径对象:
¥Returns a path object with the following keys:
state
- 目标State
(opens new window)¥
state
- the targetState
(opens new window)segments
- 具有以下形状的对象数组:¥
segments
- an array of objects with the following shape:state
- 该段的State
(opens new window)¥
state
- theState
(opens new window) of the segmentevent
- 将machine
从路径中的状态转换到下一个状态的事件对象¥
event
- the event object that transitions themachine
from the state to the next state in the path
import { createMachine } from 'xstate';
import { getSimplePaths } from '@xstate/graph';
const feedbackMachine = createMachine({
id: 'feedback',
initial: 'question',
states: {
question: {
on: {
CLICK_GOOD: 'thanks',
CLICK_BAD: 'form',
CLOSE: 'closed',
ESC: 'closed'
}
},
form: {
on: {
SUBMIT: 'thanks',
CLOSE: 'closed',
ESC: 'closed'
}
},
thanks: {
on: {
CLOSE: 'closed',
ESC: 'closed'
}
},
closed: {
type: 'final'
}
}
});
const path = getPathFromEvents(feedbackMachine, [
{ type: 'CLICK_GOOD' },
{ type: 'SUBMIT' },
{ type: 'CLOSE' }
]);
console.log(path);
// => {
// state: { value: 'closed' },
// segments: [
// {
// state: { value: 'question' },
// event: { type: 'CLICK_GOOD' },
// },
// {
// state: { value: 'form' },
// event: { type: 'SUBMIT' },
// },
// {
// state: { value: 'thanks' },
// event: { type: 'CLOSE' },
// },
// ],
// }
# toDirectedGraph(machine)
将 machine
转换为有向图结构。
¥Converts a machine
to a directed graph structure.
争论 | 类型 | 描述 |
---|---|---|
machine | 由 createMachine(...) 创建的 XState 机器 | 转换为有向图结构的机器 |
示例
¥Example
import { toDirectedGraph } from '@xstate/graph';
const machine = createMachine({/* ... */});
const digraph = toDirectedGraph(machine);
// returns an object with this structure:
{
id: '...',
stateNode: /* StateNode */,
children: [
{ id: '...', children: [/* ... */], edges: [/* ... */] },
{ id: '...', /* ... */ },
// ...
],
edges: [
{ source: /* ... */, target: /* ... */, transition: /* ... */ }
// ...
]
}
# 选项
¥Options
可以将选项传递到 getShortestPaths
或 getSimplePaths
中以自定义如何遍历机器表示的图:
¥Options can be passed into getShortestPaths
or getSimplePaths
to customize how the graph represented by the machine should be traversed:
events
- 事件类型到用于这些事件的事件对象数组的映射¥
events
- a mapping of event types to an array of event objects to be used for those eventsfilter
- 确定是否应遍历state
的函数。如果是false
,遍历算法将假定状态为 "seen" 并忽略遍历它。¥
filter
- a function that determines whether astate
should be traversed. Iffalse
, the traversal algorithm(s) will assume the state was "seen" and ignore traversing it.
示例
¥Examples
在下面的示例中,INC
事件扩展为包括两个可能的事件,其中 value: 1
和 value: 2
作为负载。它还确保 state.context.count <= 5
;否则,这台机器将被无限地遍历。
¥In the below example, the INC
event is expanded to include two possible events, with value: 1
and value: 2
as the payload. It also ensures that the state.context.count <= 5
; otherwise, this machine would be traversed infinitely.
const counterMachine = createMachine({
id: 'counter',
initial: 'active',
context: { count: 0 },
states: {
active: {
on: {
INC: {
actions: assign({ count: (ctx, e) => ctx.count + e.value })
}
}
}
}
});
const shortestPaths = getShortestPaths(counterMachine, {
events: {
INC: [
{ type: 'INC', value: 1 },
{ type: 'INC', value: 2 }
]
},
filter: (state) => state.context.count <= 5
});
console.log(shortestPaths);
// => {
// '"active" | {"count":0}': {
// state: { value: 'active', context: { count: 0 } },
// weight: 0,
// path: []
// },
// '"active" | {"count":1}': {
// state: { value: 'active', context: { count: 1 } },
// weight: 1,
// path: [
// {
// state: { value: 'active', context: { count: 0 } },
// event: { type: 'INC', value: 1 }
// }
// ]
// },
// '"active" | {"count":2}': {
// state: { value: 'active', context: { count: 2 } },
// weight: 1,
// path: [
// {
// state: { value: 'active', context: { count: 0 } },
// event: { type: 'INC', value: 2 }
// }
// ]
// },
// '"active" | {"count":3}': {
// state: { value: 'active', context: { count: 3 } },
// weight: 2,
// path: [
// {
// state: { value: 'active', context: { count: 0 } },
// event: { type: 'INC', value: 1 }
// },
// {
// state: { value: 'active', context: { count: 1 } },
// event: { type: 'INC', value: 2 }
// }
// ]
// },
// ...
// };