无事件(always)转换
无事件转换 是在没有显式事件的情况下发生的转换。这些转换在转换启用时 总是 发生。
无事件转换在 always
状态属性上指定,通常称为“always”转换。
import { createMachine } from 'xstate';
const machine = createMachine({
states: {
form: {
initial: 'valid',
states: {
valid: {},
invalid: {}
},
always: {
guard: 'isValid',
target: 'valid',
}
}
}
});
无事件转换和守卫
无事件转换在正常转换之后立即发生。它们只有在启用时才会发生,例如,当它们的守卫为真时。这使得无事件转换在某些条件为真时执行操作非常有用。
避免无限循环
没有 target
也没有 guard
的无事件转换将导致无限循环。如果 guard
一直返回 true,使用 guard
和 actions
的转换可能会遇到无限循环。
您应该通过以下方式定义无事件转换:
target
guard
+target
guard
+actions
guard
+target
+actions
如果声明了 target
,其值应与当前状态节点不同。
何时使用
当需要状态更改但没有特定触发器时,无事件转换会非常有用。
import { createMachine } from 'xstate';
const machine = createMachine({
id: 'kettle',
initial: 'lukewarm',
context: {
temperature: 80,
},
states: {
lukewarm: {
on: {
boil: { target: 'heating' }
}
},
heating: {
always: {
guard: ({ context }) => context.temperature > 100,
target: 'boiling'
}
},
boiling: {
entry: ['turnOffLight'],
always: {
guard: ({ context }) => context.temperature <= 100,
target: 'heating'
}
}
},
on: {
'temp.update': {
actions: ['updateTemperature'],
}
},
});
无事件转换和 TypeScript
无事件转换可能由任何事件启用,因此 event
类型是所有可能事件的联合。
const machine = createMachine({
types: {} as {
events:
| { type: 'greet'; message: string }
| { type: 'submit' };
},
// ...
always: {
actions: ({ event }) => {
event.type; // 'greet' | 'submit'
},
guard: ({ event }) => {
event.type; // 'greet' | 'submit'
return true;
},
},
});
无事件转换备忘单
备忘单:根无事件(always)转换
import { createMachine } from 'xstate';
const machine = createMachine({
always: {
guard: 'isValid',
actions: ['doSomething'],
},
// ...
});
Cheatsheet: state eventless (always) transition
const machine = createMachine({
initial: 'start',
states: {
start: {
always: {
guard: 'isValid',
target: 'otherState',
},
},
otherState: {/* ... */}
}
});