xstate-react
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesexState React
xState React
Your Role
你的角色
You are an expert in xState v5 actor-based state management with React and TypeScript. You understand state machines,
statecharts, the actor model, and React integration patterns for managing complex application logic.
你是精通xState v5基于actor的状态管理、并熟悉React和TypeScript的专家。你了解状态机、状态图、actor模型,以及用于管理复杂应用逻辑的React集成模式。
Overview
概述
xState is an actor-based state management and orchestration solution for JavaScript and TypeScript applications. It uses
event-driven programming, state machines, statecharts, and the actor model to handle complex logic in predictable,
robust, and visual ways.
When to use xState:
- Complex UI flows (multi-step forms, wizards, checkout processes)
- State with many transitions and edge cases
- Logic that needs to be visualized and validated
- Processes with async operations and error handling
- State that can be in multiple "modes" (loading, error, success, idle)
When to use simpler state instead (useState, Zustand):
- Simple UI toggles and counters
- Form state confined to a single component
- State without complex transition logic
- CRUD operations with straightforward loading states
xState是一款面向JavaScript和TypeScript应用的、基于actor的状态管理与编排解决方案。它采用事件驱动编程、状态机、状态图和actor模型,以可预测、健壮且可视化的方式处理复杂逻辑。
何时使用xState:
- 复杂UI流程(多步骤表单、向导、结账流程)
- 包含大量转换和边缘情况的状态
- 需要可视化和验证的逻辑
- 包含异步操作和错误处理的流程
- 可能处于多种“模式”的状态(加载中、错误、成功、空闲)
何时使用更简单的状态管理方案(useState、Zustand):
- 简单UI切换和计数器
- 局限于单个组件的表单状态
- 无复杂转换逻辑的状态
- 具有简单加载状态的CRUD操作
Quick Start
快速开始
Create a state machine and use it in a React component:
typescript
"use client";
import { createMachine } from "xstate";
import { useMachine } from "@xstate/react";
const toggleMachine = createMachine({
id: "toggle",
initial: "inactive",
states: {
inactive: {
on: { TOGGLE: "active" }
},
active: {
on: { TOGGLE: "inactive" }
}
}
});
function Toggle() {
const [state, send] = useMachine(toggleMachine);
return (
<button onClick={() => send({ type: "TOGGLE" })}>
{state.value === "inactive" ? "Off" : "On"}
</button>
);
}创建状态机并在React组件中使用:
typescript
"use client";
import { createMachine } from "xstate";
import { useMachine } from "@xstate/react";
const toggleMachine = createMachine({
id: "toggle",
initial: "inactive",
states: {
inactive: {
on: { TOGGLE: "active" }
},
active: {
on: { TOGGLE: "inactive" }
}
}
});
function Toggle() {
const [state, send] = useMachine(toggleMachine);
return (
<button onClick={() => send({ type: "TOGGLE" })}>
{state.value === "inactive" ? "Off" : "On"}
</button>
);
}React Hooks API
React Hooks API
useMachine
useMachineuseMachine
useMachineCreate and run a machine within a component's lifecycle:
typescript
import { useMachine } from "@xstate/react";
import { someMachine } from "./machines/someMachine";
function Component() {
const [state, send, actorRef] = useMachine(someMachine, {
input: { userId: "123" } // Optional input
});
return (
<div>
<p>Current state: {JSON.stringify(state.value)}</p>
<p>Context: {JSON.stringify(state.context)}</p>
<button onClick={() => send({ type: "SOME_EVENT" })}>Send</button>
</div>
);
}在组件生命周期内创建并运行状态机:
typescript
import { useMachine } from "@xstate/react";
import { someMachine } from "./machines/someMachine";
function Component() {
const [state, send, actorRef] = useMachine(someMachine, {
input: { userId: "123" } // 可选输入
});
return (
<div>
<p>当前状态: {JSON.stringify(state.value)}</p>
<p>上下文: {JSON.stringify(state.context)}</p>
<button onClick={() => send({ type: "SOME_EVENT" })}>发送事件</button>
</div>
);
}useActor
useActoruseActor
useActorSubscribe to an existing actor (created outside the component):
typescript
import { createActor } from "xstate";
import { useActor } from "@xstate/react";
import { todoMachine } from "./machines/todoMachine";
// Create actor outside component (e.g., in a module or context)
const todoActor = createActor(todoMachine);
todoActor.start();
function TodoApp() {
const [state, send] = useActor(todoActor);
return (
<ul>
{state.context.todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}订阅已有的actor(在组件外部创建):
typescript
import { createActor } from "xstate";
import { useActor } from "@xstate/react";
import { todoMachine } from "./machines/todoMachine";
// 在组件外部创建actor(例如在模块或上下文环境中)
const todoActor = createActor(todoMachine);
todoActor.start();
function TodoApp() {
const [state, send] = useActor(todoActor);
return (
<ul>
{state.context.todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}useSelector
useSelectoruseSelector
useSelectorOptimize re-renders by selecting specific state:
typescript
import { useSelector } from "@xstate/react";
function TodoCount({ actorRef }) {
// Only re-renders when todos.length changes
const count = useSelector(actorRef, (state) => state.context.todos.length);
return <span>{count} todos</span>;
}
function IsLoading({ actorRef }) {
// Only re-renders when loading state changes
const isLoading = useSelector(actorRef, (state) => state.matches("loading"));
return isLoading ? <Spinner /> : null;
}通过选择特定状态来优化重渲染:
typescript
import { useSelector } from "@xstate/react";
function TodoCount({ actorRef }) {
// 仅当todos.length变化时才重渲染
const count = useSelector(actorRef, (state) => state.context.todos.length);
return <span>{count} 个待办事项</span>;
}
function IsLoading({ actorRef }) {
// 仅当加载状态变化时才重渲染
const isLoading = useSelector(actorRef, (state) => state.matches("loading"));
return isLoading ? <Spinner /> : null;
}TypeScript Patterns
TypeScript模式
Typing Machines with types
types使用types
为状态机添加类型
typesDefine context and events using the property:
typestypescript
import { createMachine, assign } from "xstate";
type FormContext = {
name: string;
email: string;
errors: string[];
};
type FormEvent =
| { type: "UPDATE_NAME"; value: string }
| { type: "UPDATE_EMAIL"; value: string }
| { type: "SUBMIT" }
| { type: "RESET" };
const formMachine = createMachine({
types: {} as {
context: FormContext;
events: FormEvent;
},
id: "form",
initial: "editing",
context: {
name: "",
email: "",
errors: []
},
states: {
editing: {
on: {
UPDATE_NAME: {
actions: assign({
name: ({ event }) => event.value
})
},
UPDATE_EMAIL: {
actions: assign({
email: ({ event }) => event.value
})
},
SUBMIT: "submitting"
}
},
submitting: {
// ...
}
}
});通过属性定义上下文和事件:
typestypescript
import { createMachine, assign } from "xstate";
type FormContext = {
name: string;
email: string;
errors: string[];
};
type FormEvent =
| { type: "UPDATE_NAME"; value: string }
| { type: "UPDATE_EMAIL"; value: string }
| { type: "SUBMIT" }
| { type: "RESET" };
const formMachine = createMachine({
types: {} as {
context: FormContext;
events: FormEvent;
},
id: "form",
initial: "editing",
context: {
name: "",
email: "",
errors: []
},
states: {
editing: {
on: {
UPDATE_NAME: {
actions: assign({
name: ({ event }) => event.value
})
},
UPDATE_EMAIL: {
actions: assign({
email: ({ event }) => event.value
})
},
SUBMIT: "submitting"
}
},
submitting: {
// ...
}
}
});Using setup()
for Reusable Definitions
setup()使用setup()
定义可复用内容
setup()Define actions, guards, actors, and delays in a type-safe way:
typescript
import { setup, assign } from "xstate";
type AuthContext = {
userId: string | null;
retries: number;
};
type AuthEvent =
| { type: "LOGIN"; username: string; password: string }
| { type: "LOGOUT" }
| { type: "SUCCESS"; userId: string }
| { type: "FAILURE" };
const authMachine = setup({
types: {} as {
context: AuthContext;
events: AuthEvent;
},
actions: {
setUser: assign({
userId: ({ event }) => (event as { userId: string }).userId
}),
clearUser: assign({
userId: null,
retries: 0
}),
incrementRetries: assign({
retries: ({ context }) => context.retries + 1
})
},
guards: {
hasReachedMaxRetries: ({ context }) => context.retries >= 3,
isAuthenticated: ({ context }) => context.userId !== null
}
}).createMachine({
id: "auth",
initial: "loggedOut",
context: { userId: null, retries: 0 },
states: {
loggedOut: {
on: {
LOGIN: "authenticating"
}
},
authenticating: {
on: {
SUCCESS: {
target: "loggedIn",
actions: "setUser"
},
FAILURE: [
{
guard: "hasReachedMaxRetries",
target: "loggedOut",
actions: "clearUser"
},
{
actions: "incrementRetries"
}
]
}
},
loggedIn: {
on: {
LOGOUT: {
target: "loggedOut",
actions: "clearUser"
}
}
}
}
});以类型安全的方式定义动作、守卫、actor和延迟:
typescript
import { setup, assign } from "xstate";
type AuthContext = {
userId: string | null;
retries: number;
};
type AuthEvent =
| { type: "LOGIN"; username: string; password: string }
| { type: "LOGOUT" }
| { type: "SUCCESS"; userId: string }
| { type: "FAILURE" };
const authMachine = setup({
types: {} as {
context: AuthContext;
events: AuthEvent;
},
actions: {
setUser: assign({
userId: ({ event }) => (event as { userId: string }).userId
}),
clearUser: assign({
userId: null,
retries: 0
}),
incrementRetries: assign({
retries: ({ context }) => context.retries + 1
})
},
guards: {
hasReachedMaxRetries: ({ context }) => context.retries >= 3,
isAuthenticated: ({ context }) => context.userId !== null
}
}).createMachine({
id: "auth",
initial: "loggedOut",
context: { userId: null, retries: 0 },
states: {
loggedOut: {
on: {
LOGIN: "authenticating"
}
},
authenticating: {
on: {
SUCCESS: {
target: "loggedIn",
actions: "setUser"
},
FAILURE: [
{
guard: "hasReachedMaxRetries",
target: "loggedOut",
actions: "clearUser"
},
{
actions: "incrementRetries"
}
]
}
},
loggedIn: {
on: {
LOGOUT: {
target: "loggedOut",
actions: "clearUser"
}
}
}
}
});Core Concepts
核心概念
States and Transitions
状态与转换
States represent the possible modes of your system. Transitions define how events move between states:
typescript
const machine = createMachine({
initial: "idle",
states: {
idle: {
on: { FETCH: "loading" }
},
loading: {
on: {
SUCCESS: "success",
ERROR: "error"
}
},
success: { type: "final" },
error: {
on: { RETRY: "loading" }
}
}
});状态代表系统的可能模式。转换定义了事件如何在状态间切换:
typescript
const machine = createMachine({
initial: "idle",
states: {
idle: {
on: { FETCH: "loading" }
},
loading: {
on: {
SUCCESS: "success",
ERROR: "error"
}
},
success: { type: "final" },
error: {
on: { RETRY: "loading" }
}
}
});Context
上下文
Context holds extended state data:
typescript
const machine = createMachine({
context: {
count: 0,
user: null
},
// ...
});
// Access in component
const count = state.context.count;上下文存储扩展状态数据:
typescript
const machine = createMachine({
context: {
count: 0,
user: null
},
// ...
});
// 在组件中访问
const count = state.context.count;Actions
动作
Actions are fire-and-forget side effects:
typescript
import { assign } from "xstate";
const machine = createMachine({
// ...
states: {
active: {
entry: assign({ count: ({ context }) => context.count + 1 }),
exit: () => console.log("Leaving active state")
}
}
});动作是一次性的副作用:
typescript
import { assign } from "xstate";
const machine = createMachine({
// ...
states: {
active: {
entry: assign({ count: ({ context }) => context.count + 1 }),
exit: () => console.log("离开active状态")
}
}
});Best Practices
最佳实践
DO
建议
- Use for type-safe action and guard definitions
setup() - Use for optimized state selection
useSelector - Define explicit types for context and events
- Use for hierarchical state checking
state.matches() - Keep machines pure and side-effect-free (use actions for effects)
- 使用进行类型安全的动作和守卫定义
setup() - 使用优化状态选择
useSelector - 为上下文和事件定义明确的类型
- 使用检查分层状态
state.matches() - 保持状态机纯净且无副作用(使用动作处理副作用)
DON'T
不建议
- Don't store the entire snapshot object in React state
- Don't mutate context directly (use )
assign - Don't use xState for simple toggle/counter state
- Don't forget to handle all possible states in your UI
- 不要在React状态中存储整个快照对象
- 不要直接修改上下文(使用)
assign - 不要将xState用于简单的切换/计数器状态
- 不要忘记在UI中处理所有可能的状态
Client Component Requirement
客户端组件要求
xState hooks must be used in Client Components. Add the directive:
"use client"typescript
"use client";
import { useMachine } from "@xstate/react";xState钩子必须在客户端组件中使用。添加指令:
"use client"typescript
"use client";
import { useMachine } from "@xstate/react";Additional Documentation
额外文档
For comprehensive xState documentation including advanced patterns, use the Context7 MCP:
Use Context7 MCP with library ID "/statelyai/xstate" to fetch:
- Detailed invoke/spawn patterns
- Parallel and history states
- Actor communication
- Testing strategiesSee for common patterns including async operations, guards, parallel states, and
persistence.
./references/patterns.md如需包含高级模式的完整xState文档,请使用Context7 MCP:
使用库ID为"/statelyai/xstate"的Context7 MCP获取:
- 详细的invoke/spawn模式
- 并行状态和历史状态
- Actor通信
- 测试策略查看 获取包含异步操作、守卫、并行状态和持久化的常见模式。
./references/patterns.mdQuick Reference
快速参考
| Task | Pattern |
|---|---|
| Create machine | |
| Use in component | |
| Check state | |
| Send event | |
| Read context | |
| Update context | |
| Conditional | |
| Async operation | |
| Optimized select | |
| 任务 | 实现模式 |
|---|---|
| 创建状态机 | |
| 在组件中使用 | |
| 检查状态 | |
| 发送事件 | |
| 读取上下文 | |
| 更新上下文 | |
| 条件判断 | |
| 异步操作 | |
| 优化状态选择 | |