# 模块
¥Models
这些 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).
警告
createModel(...) 函数已弃用,并将在 XState 版本 5 中删除。建议使用 类型基因 (opens new window) 代替。
¥The createModel(...) function is deprecated and will be removed in XState version 5. It is recommended to use Typegen (opens new window) instead.
在 XState 中,你可以使用 createModel(...) 在外部对机器的 context 和 events 进行建模。这提供了一种强类型 context 和 events 的便捷方法,以及将来事件创建、分配和其他实现细节的辅助程序。
¥In XState, you can model a machine's context and events externally by using createModel(...). This provides a convenient way to strongly type context and events, as well as helpers for event creation, assignment and other implementation details in the future.
使用 createModel(...) 是完全可选的,旨在改善开发者体验。使用它的主要原因是:
¥Using createModel(...) is completely optional, and is meant to improve the developer experience. The main reasons for using it are:
以强类型的方式分离和组织
context和events¥Separating and organizing
contextandeventsin a strongly-typed way防止
assign(...)出现打字问题¥Preventing typing issues with
assign(...)指定事件创建者以更轻松、更安全地创建事件
¥Specifying event creators for easier and safer event creation
可能与其他机器共享模型
¥Potentially sharing the model with other machines
未来的开发者体验改进,例如指定操作、防护等。
¥Future developer experience improvements, such as specifying actions, guards, etc.
# createModel(...)
createModel(...) 函数需要
¥The createModel(...) function takes
| 争论 | 类型 | 描述 |
|---|---|---|
initialContext | object | 初始 context 值 |
creators(可选) | object | 包含各种事件创建者的对象 |
creators 对象包括以下属性:
¥The creators object includes the following properties:
| 争论 | 类型 | 描述 |
|---|---|---|
events | object | 包含事件创建者的对象 |
creators.events 对象的键是事件类型,值是接受任意数量的参数并返回事件负载的函数。
¥The keys of the creators.events object are event types, and the values are functions that accept any number of arguments and return the event payload.
# 建模环境
¥Modeling context
由于模型定义了机器的 context,因此可以在机器定义中使用该模型,将其初始 context 设置为 model.initialContext,并使用 model.assign 更新机器的 context。
¥Since the model defines the machine's context, the model can be used within the machine definition to set its initial context with model.initialContext and to update the machine's context with model.assign.
model.assign 功能是按照模型 context 的形状设计的,使其成为 assign 动作的方便且类型安全的替代品。
¥The model.assign function is typed to the shape of the model's context, making it a convenient and type-safe replacement for the assign action.
import { createModel } from 'xstate/lib/model';
const userModel = createModel({
name: 'Someone',
age: 0
});
// ...
const machine = userModel.createMachine({
context: userModel.initialContext,
// ...
entry: userModel.assign({ name: '' })
});
# 建模事件
¥Modeling events
在模型中对机器事件进行建模有两个好处:
¥Modeling machine events in a model gives two benefits:
可以通过调用
model.events.eventName(...)创建事件¥Events can be created by calling
model.events.eventName(...)向机器定义提供类型信息,为操作定义提供特定于事件的类型安全性
¥Provides type information to the machine definition, providing event-specific type safety for action definitions
import { createModel } from 'xstate/lib/model';
const userModel = createModel(
// Initial context
{
name: 'David',
age: 30
},
{
// Event creators
events: {
updateName: (value) => ({ value }),
updateAge: (value) => ({ value }),
anotherEvent: () => ({}) // no payload
}
}
);
const machine = userModel.createMachine(
{
context: userModel.initialContext,
initial: 'active',
states: {
active: {
on: {
updateName: {
actions: userModel.assign({
name: (_, event) => event.value
})
},
updateAge: {
actions: 'assignAge'
}
}
}
}
},
{
actions: {
assignAge: userModel.assign({
age: (_, event) => event.value
})
}
}
);
// This sends the following event:
// {
// type: 'updateName',
// value: 'David'
// }
const nextState = machine.transition(
undefined,
userModel.events.updateName('David')
);
# TypeScript
createModel(...) 函数推断以下类型:
¥The createModel(...) function infers the following types:
context是从createModel(initialContext, creators)中的第一个参数推断出来的¥
contextis inferred from the first argument increateModel(initialContext, creators)events是从createModel(initialContext, creators)中的creators.events推断出来的¥
eventsis inferred fromcreators.eventsincreateModel(initialContext, creators)
import { createModel } from 'xstate/lib/model';
const userModel = createModel(
{
name: 'David', // inferred as `string`
age: 30, // inferred as `number`
friends: [] as string[] // explicit type
},
{
events: {
updateName: (value: string) => ({ value }),
updateAge: (value: number) => ({ value }),
anotherEvent: () => ({}) // no payload
}
}
);
// Context inferred as:
// {
// name: string;
// age: number;
// friends: string[];
// }
// Events inferred as:
// | { type: 'updateName'; value: string; }
// | { type: 'updateAge'; value: number; }
// | { type: 'anotherEvent'; }
# 从模型创建机器
¥Creating a machine from a model
应使用 model.createMachine(...) 方法,而不是将 context 和 event 的类型显式指定为 createMachine<TContext, TEvent>(...) 中的类型参数:
¥Instead of specifying the type of context and event explicitly as type parameters in createMachine<TContext, TEvent>(...), the model.createMachine(...) method should be used:
const machine = userModel.createMachine({
context: userModel.initialContext,
initial: 'active',
states: {
active: {
on: {
updateName: {
actions: userModel.assign({
name: (_, event) => event.value // inferred
})
}
}
}
}
});
# 缩小分配事件类型
¥Narrowing assign event types
当 options.actions 中引用 assign() 操作时,你可以在 model.assign(assignments, eventType) 的第二个参数中缩小该操作接受的事件类型:
¥When an assign() action is referenced in options.actions, you can narrow the event type that the action accepts in the 2nd argument of model.assign(assignments, eventType):
const assignAge = userModel.assign(
{
// The `event.type` here is restricted to "updateAge"
age: (_, event) => event.value // inferred as `number`
},
'updateAge' // Restricts the `event` allowed by the "assignAge" action
);
const machine = userModel.createMachine({
context: userModel.initialContext,
initial: 'active',
states: {
active: {
on: {
updateAge: {
actions: assignAge
}
}
}
}
});
警告
具有缩小事件类型的分配操作不能放置在 createMachine(configuration, options) 中计算机选项的 actions: {...} 属性内。这是因为应假定 options.actions 中的操作可能接收任何事件,即使机器配置另有建议。
¥Assign actions with narrowed event types cannot be placed inside the actions: {...} property of machine options in createMachine(configuration, options). This is because actions in options.actions should be assumed to potentially receive any event, even if the machine configuration suggests otherwise.
# 从模型中提取类型
¥Extracting types from model
自 4.22.1 起
¥Since 4.22.1
你可以使用 ContextFrom<T> 和 EventFrom<T> 类型从模型中提取 context 和 event 类型:
¥You can extract context and event types from a model using the ContextFrom<T> and EventFrom<T> types:
import { ContextFrom, EventFrom } from 'xstate';
import { createModel } from 'xstate/lib/model';
const someModel = createModel(
{
/* ... */
},
{
events: {
/* ... */
}
}
);
type SomeContext = ContextFrom<typeof someModel>;
type SomeEvent = EventFrom<typeof someModel>;