Model complex UI logic with XState state machines. Use when a user asks to manage complex multi-step flows, model stateful UI (wizards, forms, auth), prevent impossible states, or implement finite state machines in JavaScript.
XState models application logic as state machines. Instead of managing boolean flags (isLoading, isError, isSuccess), you define states and transitions explicitly — making impossible states impossible. Ideal for complex flows: checkout, onboarding, authentication, multi-step forms.
// machines/authMachine.ts — Authentication state machine
import { setup, assign, fromPromise } from 'xstate'
export const authMachine = setup({
types: {
context: {} as {
user: { id: string; name: string; email: string } | null
error: string | null
retries: number
},
events: {} as
| { type: 'LOGIN'; email: string; password: string }
| { type: 'LOGOUT' }
| { type: 'RETRY' },
},
actors: {
loginUser: fromPromise(async ({ input }: { input: { email: string; password: string } }) => {
const res = await fetch('/api/auth/login', {
method: 'POST',
body: JSON.stringify(input),
})
if (!res.ok) throw new Error('Invalid credentials')
return res.json()
}),
},
}).createMachine({
id: 'auth',
initial: 'idle',
context: { user: null, error: null, retries: 0 },
states: {
idle: {
on: { LOGIN: 'authenticating' },
},
authenticating: {
invoke: {
src: 'loginUser',
input: ({ event }) => ({ email: event.email, password: event.password }),
onDone: {
target: 'authenticated',
actions: assign({ user: ({ event }) => event.output, error: null }),
},
onError: {
target: 'error',
actions: assign({
error: ({ event }) => event.error.message,
retries: ({ context }) => context.retries + 1,
}),
},
},
},
authenticated: {
on: { LOGOUT: { target: 'idle', actions: assign({ user: null }) } },
},
error: {
on: {
RETRY: { target: 'authenticating', guard: ({ context }) => context.retries < 3 },
LOGIN: 'authenticating',
},
},
},
})
// components/LoginPage.tsx — XState in React
import { useMachine } from '@xstate/react'
import { authMachine } from '../machines/authMachine'
export function LoginPage() {
const [state, send] = useMachine(authMachine)
if (state.matches('authenticated')) {
return <div>Welcome, {state.context.user.name}!</div>
}
return (
<form onSubmit={(e) => {
e.preventDefault()
const form = new FormData(e.currentTarget)
send({
type: 'LOGIN',
email: form.get('email') as string,
password: form.get('password') as string,
})
}}>
<input name="email" type="email" required />
<input name="password" type="password" required />
{state.matches('error') && (
<p className="error">{state.context.error}</p>
)}
<button disabled={state.matches('authenticating')}>
{state.matches('authenticating') ? 'Signing in...' : 'Sign In'}
</button>
{state.matches('error') && state.context.retries < 3 && (
<button type="button" onClick={() => send({ type: 'RETRY' })}>
Retry ({3 - state.context.retries} left)
</button>
)}
</form>
)
}
npx skills add TerminalSkills/xstate下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer