入门

我们的第一个状态机

假设我们使用 Promise 创建状态机。首先,使用 NPM 或 Yarn 安装 XState:

  1. npm install xstate --save

如果你正在使用 VSCode,你应该安装我们的 VSCode Extension,以便你可以随时可视化你正在构建的状态机。

然后,在你的项目中,导入 createMachine,这是一个创建状态机的函数。

  1. import { createMachine } from 'xstate';
  2. const promiseMachine = createMachine(/* ... */);

我们将 状态机配置 传递到 createMachine。我们需要提供:

  • id - 去标识状态机
  • initial - 指定这台状态机应该处于的初始状态节点
  • states - 定义每个子状态:
  1. import { createMachine } from 'xstate';
  2. const promiseMachine = createMachine({
  3. id: 'promise',
  4. initial: 'pending',
  5. states: {
  6. pending: {},
  7. resolved: {},
  8. rejected: {}
  9. }
  10. });

然后,我们需要向状态节点添加 转换(transitions)

  1. import { createMachine } from 'xstate';
  2. const promiseMachine = createMachine({
  3. id: 'promise',
  4. initial: 'pending',
  5. states: {
  6. pending: {
  7. on: {
  8. RESOLVE: { target: 'resolved' },
  9. REJECT: { target: 'rejected' }
  10. }
  11. },
  12. resolved: {},
  13. rejected: {}
  14. }
  15. });

我们还需要将 resolvedrejected 的状态节点标记为 最终状态节点,因为 promise 状态机一旦达到这些状态就会终止运行:

  1. import { createMachine } from 'xstate';
  2. const promiseMachine = createMachine({
  3. id: 'promise',
  4. initial: 'pending',
  5. states: {
  6. pending: {
  7. on: {
  8. RESOLVE: { target: 'resolved' },
  9. REJECT: { target: 'rejected' }
  10. }
  11. },
  12. resolved: {
  13. type: 'final'
  14. },
  15. rejected: {
  16. type: 'final'
  17. }
  18. }
  19. });

我们的状态机现在可以进行可视化了。你可以复制/粘贴上面的代码并在 Stately Viz 可视化它。看起来这样:

运行我们的状态机

我们如何运行我们的状态机,取决于我们计划在哪里使用它。

在 Node/Vanilla JS

为了 解释(interpret) 状态机并使其运行,我们需要添加一个解释器。这将创建一个服务:

  1. import { createMachine, interpret } from 'xstate';
  2. const promiseMachine = createMachine({
  3. /* ... */
  4. });
  5. const promiseService = interpret(promiseMachine).onTransition((state) =>
  6. console.log(state.value)
  7. );
  8. // 开启 service
  9. promiseService.start();
  10. // => 'pending'
  11. promiseService.send({ type: 'RESOLVE' });
  12. // => 'resolved'

在 React

如果我们想在 React 组件中使用我们的状态机,我们可以使用 useMachine Hook:

你需要安装 @xstate/react

  1. import { useMachine } from '@xstate/react';
  2. const Component = () => {
  3. const [state, send] = useMachine(promiseMachine);
  4. return (
  5. <div>
  6. {/** 你可以监听 service 处于什么状态 */}
  7. {state.matches('pending') && <p>Loading...</p>}
  8. {state.matches('rejected') && <p>Promise Rejected</p>}
  9. {state.matches('resolved') && <p>Promise Resolved</p>}
  10. <div>
  11. {/** 你可以发送事件到运行的 service 中 */}
  12. <button onClick={() => send('RESOLVE')}>Resolve</button>
  13. <button onClick={() => send('REJECT')}>Reject</button>
  14. </div>
  15. </div>
  16. );
  17. };