# @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 - xstateand- @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- the- Machine(opens new window) to traverse
- options(可选) - 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 target- State(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- the- State(opens new window) of the segment
- weight- 路径总 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 the- machinefrom 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- the- Machine(opens new window) to traverse
- options(可选) - 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 target- State(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- the- State(opens new window) of the segment
- event- 将- machine从路径中的状态转换到下一个状态的事件对象- ¥ - event- the event object that transitions the- machinefrom 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- the- Machine(opens new window) to traverse
- events- 生成路径的事件序列- ¥ - 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 target- State(opens new window)
- segments- 具有以下形状的对象数组:- ¥ - segments- an array of objects with the following shape:- state- 该段的- State(opens new window)- ¥ - state- the- State(opens new window) of the segment
- event- 将- machine从路径中的状态转换到下一个状态的事件对象- ¥ - event- the event object that transitions the- machinefrom 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 events
- filter- 确定是否应遍历- state的函数。如果是- false,遍历算法将假定状态为 "seen" 并忽略遍历它。- ¥ - filter- a function that determines whether a- stateshould be traversed. If- false, 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 }
//       }
//     ]
//   },
//   ...
// };