代码没报错,状态也切过去了,只有那个计数器变成了NaN。这是 XState v4 写法跑在 v5 上时,最容易漏掉的一种翻车方式。
XState v5 在 2023 年 12 月发布,迁移指南里列了一条破坏性变更:实现函数现在只接收一个对象参数,里面带着context、event以及其他属性。这条变更看起来不起眼,但踩上去的人不少。
用 v4 风格写的代码,在 xstate 5.33.2 上依然"看起来没问题"。下面这段就是典型的 v4 写法:
- createMachine建机器,初始状态 red,context 里放一个 cycles: 0
- red 状态收到 NEXT 事件后,target 指向 green
- actions 里用assign更新 cycles,回调写成(context, event) => context.cycles + 1
- 再用 createActor 启动,send 一个 NEXT,打印快照
跑出来的结果是:actor.getSnapshot().value是 "green",状态切换正常;但actor.getSnapshot().context.cycles是NaN。没有异常抛出,机器照常往前走,只有那个计数器安静地错了。
原因在参数形状上。v5 里第一个参数是{ context, event }这个对象,所以context.cycles取到的是 undefined,undefined 加 1 就是 NaN。整个过程不声不响,日志里也不会留下痕迹。
改法只有一行。把回调从(context, event) => context.cycles + 1换成({ context }) => context.cycles + 1,从对象里解构出 context,计数器就恢复正常。
ProvenPin 上有一个叫xstate-v5-traffic-light的配方,用 createMachine、createActor、guards 和 context 更新完整模拟了一个红绿灯。它锁定 xstate 5.33.2、tsx 4.23.15 和 @types/node 26.6.5,在 Node v22.23.3 上于 2026 年 10 月 18 日通过了 CI 里的 2 项测试中的 2 项。
这个配方可以直接喂给编码 agent 用。ProvenPin 是一个免费的 MCP 服务器,不需要 API key,也不用注册。接入方式是在命令行执行:
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
Cursor 则在~/.cursor/mcp.json里配置:
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }
配好之后,直接向 agent 要"一个经过测试的 XState v5 配方",或者调用get_recipe("xstate-v5-traffic-light")。VS Code、Windsurf 和 Cline 的配置方式在文档里。
这类迁移坑的共同点是:类型系统不拦,运行时也不喊,只有业务数据在某个角落慢慢变歪。状态机切对了,计数器错了,排查的时候往往先怀疑状态逻辑,最后才发现是参数解构没跟上版本。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.