Skip to content

Context

基本概念

Context 就是状态机里的“数据仓库”

Context 是所有 state 共用的

Context 是 只读的(不可直接修改)

不是每个 state 有一份,而是 整个状态机一份

ts
import { createMachine, createActor } from 'xstate';

const feedbackMachine = createMachine({
  // Initialize the state machine with context
  context: {
    feedback: 'Some feedback',
  },
});

const feedbackActor = createActor(feedbackMachine);

feedbackActor.subscribe((state) => {
  console.log(state.context.feedback);
});

feedbackActor.start();
// logs 'Some feedback'

初始化 context

lazy Initial context

context支持使用函数,每个 actor 都会拥有自己独立的 context 对象。

ts
const feedbackMachine = createMachine({
  context: () => ({
    feedback: 'Some feedback',
    createdAt: Date.now(),
  }),
});

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

console.log(feedbackActor.getSnapshot().context.createdAt);
// logs the current timestamp

传入context

你可以在创建 actor 时,通过 createActor(machine, { input }) 传入 input 数据,并在 context 函数中从第一个参数里读取 input

ts
import { setup, createActor } from 'xstate';

const feedbackMachine = setup({
  types: {
    context: {} as {
      feedback: string;
      rating: number;
    },
    input: {} as {
      defaultRating: number;
    },
  },
}).createMachine({
  context: ({ input }) => ({
    feedback: '',
    rating: input.defaultRating,
  }),
});

const feedbackActor = createActor(feedbackMachine, {
  input: {
    defaultRating: 5,
  },
}).start();

console.log(feedbackActor.getSnapshot().context.rating);
// logs 5

修改context

在状态转换中,使用 assign(...) action 来更新 context:

ts
assign(Object)

Object的key是context的key

直接值

value是直接值

ts
assign({
  feedback: 'hello',
})

函数

value是函数,这个函数接收event,event是传入send的事件对象EventObject

ts
send({
  type: 'SUBMIT',
  feedback: '很好用',
})
ts
assign({
  feedback: ({ event }) => {
    // event 就是:
    // { type: 'SUBMIT', feedback: '很好用' }
    return event.feedback
  },
})
ts
import { createMachine, assign, createActor } from 'xstate';

const feedbackMachine = createMachine({
  context: {
    feedback: 'Some feedback',
  },
  on: {
    'feedback.update': {
      actions: assign({
        feedback: ({ event }) => event.feedback,
      }),
    },
  },
});

const feedbackActor = createActor(feedbackMachine);

feedbackActor.subscribe((state) => {
  console.log(state.context.feedback);
});

feedbackActor.start();

// logs 'Some feedback'

feedbackActor.send({
  type: 'feedback.update',
  feedback: 'Some other feedback',
});

// logs 'Some other feedback'

TS

在setup中可以声明context的类型

ts
import { setup } from 'xstate';

const machine = setup({
  types: {} as {
    context: {
      feedback: string;
      rating: number;
    };
  },
}).createMachine({
  // Initial context
  context: {
    feedback: '',
    rating: 5,
  },
  entry: ({ context }) => {
    context.feedback; // string
    context.rating; // number
  },
});