# 模块
¥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
context
andevents
in 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)
中的第一个参数推断出来的¥
context
is inferred from the first argument increateModel(initialContext, creators)
events
是从createModel(initialContext, creators)
中的creators.events
推断出来的¥
events
is inferred fromcreators.events
increateModel(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>;