Skip to content

States

states 是整个状态机的核心,用于声明「有哪些状态」以及「每个状态能做什么」。

ts
end: {
  description: '结束',
  type: 'final',
  meta: {
    index: 6,
    component: markRaw(END),
    title: '一审结束',
    disabled: true,
  },
},

每个 states.xxx 都是一个 状态节点配置对象

tags

tag 是你给“状态节点”贴的语义标签,和层级、名字无关,只表达“这个状态属于哪一类”。

ts
const feedbackMachine = createMachine({
  // ...
  states: {
    submitting: {
      tags: ['loading'],
      // ...
    },
  },
});

const feedbackActor = createActor(feedbackMachine).start();

const currentState = feedbackActor.getSnapshot();

const showLoadingSpinner = currentState.hasTag('loading');

description

State descriptions(状态描述)。它不影响状态机运行,但对协作、可维护性、可视化非常重要。

State descriptions 是写给“人”看的说明文字,用来解释“这个状态是干嘛的”。用于文档、协作、可视化(尤其是 Stately Studio)。

meta

给 UI 用的状态信息

ts
meta: {
  layout: 'fullscreen',
  authRequired: true,
  title: '提交成功',
}
对比metacontext
是否可变❌ 不可变✅ assign
生命周期定义期运行期
作用描述状态保存数据
是否参与逻辑
UI 配置✅ 非常适合❌ 不推荐

on

用于定义当前状态存在哪些事件,相当于声明了事件监听器,事件一般使用大写表示。具体参见:Transitions

on表示当状态处于当前节点,并且收到某个事件时,该怎么反应

invoke

invoke表示进入这个状态后,自动启动一个 Actor,并管理它的生命周期

ts
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",
        },
      ],
    },
  },
}

entry

进入状态时执行的Action

ts
loading: {
  entry: 'startLoading',
  exit: 'stopLoading'
}

exit

离开当前状态时执行的Action

always

无事件的自动迁移

type

定义当前事件的特殊类型

ts
final | parallel | history

普通状态

不声明type的值的状态就是普通状态

final

一旦进入该状态

当前这个 state node 所在的 machine / 子 machine 就结束

snapshot.status === 'done'

parallel

并行状态:同一时间同时处于多个子状态

ts
working: {
  type: 'parallel',
  states: {
    form: {},
    attachment: {}
  }
}

snapshot.value:

ts
{
  working: {
    form: 'idle',
    attachment: 'uploading'
  }
}

history

记住上一次的子状态

ts
import { createMachine } from 'xstate'

const panelMachine = createMachine({
  id: 'panel',
  initial: 'panel',
  states: {
    panel: {
      initial: 'list',
      states: {
        list: {
          on: { VIEW: 'detail' }
        },
        detail: {
          on: { BACK: 'list' }
        },
        history: {
          type: 'history'//可以记住上次的状态是list还是detail
        }
      },
      on: {
        LEAVE: 'other'
      }
    },
    other: {
      on: {
        ENTER: 'panel.history'
      }
    }
  }
})

结果:

ts
panel.list
VIEW → panel.detail
LEAVE → other
ENTER → panel.detail   ✅(自动回到 detail)

states

状态还可以嵌套声明子状态:

ts
trial: {
  description: '开庭',
  initial: 'notice',
  meta: {
    index: 3,
    component: markRaw(Step3),
    title: '开庭',
  },
  states: {
    notice: {
      meta: { index: 3.1, title: '开庭' },
      description: '收到开庭通知',
      on: {
        NEXT: {
          target: 'wait',
          actions: assign({
            progressId: 17,
          }),
        },
      },
    },
    wait: {
      meta: { index: 3.2, title: '等待开庭', disabled: true },
      description: '开庭中',
      on: {
        NEXT: {
          target: 'end',
        },
      },
    },
    // 后端生成的记录nextKey:end
    end: {
      meta: { index: 3.3, title: '庭审结束' },
      description: '庭审结束',
      on: {
        NEXT: {
          target: '#firstTrial.trialMediation',
          actions: 'resetProgressId',
        },
      },
    },
  },
},

output

states 里,output 只能写在 type: 'final'` 的状态上。当状态机“走到这个 final 状态时”,产出的最终结果

  • 静态值
ts
success: {
  type: 'final',
  output: {
    result: 'ok'
  }
}
  • 函数
ts
success: {
  type: 'final',
  output: ({ context }) => ({
    result: 'ok'
  })
}