Skip to content
目录

中间件系统

中间件是 包一层再包一层的 StateCreator:在不改 Vanilla 核心的前提下增强 set / get / store。入口类型在 src/middleware.ts,各中间件在 src/middleware/*.ts


1. 组合模型

text
create( devtools( persist( immer( (set, get, store) => ({ ... }) ) ) ) )

执行顺序:由内到外

  1. 最内层:用户 StateCreator 定义 state 与 actions。
  2. 向外:每层中间件包装上一层的 set/get(如 Immer 改 set 语义,persist 在 set 后写 storage,devtools 记录 action)。

记忆:先写的中间件离 state 最近,最外层最先接到 create 调用。

需求常见顺序(内 → 外)
不可变 + 持久化 + 调试immerpersistdevtools

2. 常见中间件职责

中间件作用注意
immerset 接收 draft,深层修改与「手写展开」二选一即可
persist序列化到 localStorage 等partialize 控制字段;注意 SSR 与水合
devtools对接 Redux DevTools生产关闭
redux兼容 reducer + dispatch 形态迁移 Redux 时用
subscribeWithSelectorsubscribe(selector, listener)非 React 侧细粒度监听
combine合并多个 slice 初始状态与 actions大 store 拆分

不必背诵各文件实现;抓住「拦截 set/get」即可推断行为。


3. 类型与 mutator

TypeScript 下中间件通过 StoreMutatorIdentifier 把增强能力(如 persist 的 persist API)合并进 store 类型。多个中间件时类型从左到右(或按库定义)折叠。

若类型报错,优先查官方文档的 middleware 组合示例,而非手写 any 绕过。


4. 自定义中间件(思路)

自定义中间件 = (config) => (set, get, api) => config( wrappedSet, get, api )

  • wrappedSet 里:日志、埋点、节流、乐观更新写回。
  • 避免无限递归:始终调用「内层 set」而非自己。

5. 性能与陷阱

  • 每层中间件增加一次函数调用;生产只保留必要层。
  • persist 同步 IO 可能卡主线程;大状态考虑异步存储或拆分。
  • devtools 序列化整个 state 有成本。

6. 总结

中间件 = 高阶 StateCreator;理解组合顺序与 set 拦截点即可排查「为什么 persist 没存」「为什么 DevTools 没动作」。状态合并语义仍由 Vanilla 05-状态更新 决定,Immer 只改变你如何写 set 的参数。

MIT License.