Skip to content
目录

React 集成机制

React 层(src/react.ts)把 Vanilla Store 接到组件树:useSyncExternalStore + 选择器。这是 Zustand 在 React 18 并发下避免 tearing 与僵尸子组件问题的关键。


1. 为什么不用 useState + useEffect 订阅

旧模式:mount 时 getState + subscribesetState

问题表现
Tearing同一次渲染中不同组件读到不同版本的 store
僵尸子组件已卸载组件的订阅回调仍跑,闭包里是过期 props/state
SSR 不一致服务端与客户端首帧快照可能对不齐

React 18 的 useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?) 为「外部 store」规定了订阅与快照协议,Zustand 直接复用。


2. useStore 做了什么

概念上三步:

  1. subscribe:用 store 的 subscribe,由 React 管理挂载/卸载。
  2. getSnapshotselector(getState());React 用 Object.is 比较连续两次快照,相同则不重渲染。
  3. getServerSnapshot(可选):selector(getInitialState()),SSR 首帧与客户端水合对齐。

create() 返回的 Hook 本质是 useStore(storeApi, selector);默认 selector 为整棵 state(不推荐在生产大 store 上使用)。

选择器应用 useCallback 稳定引用:selector 引用变会导致 getSnapshot 依赖变,可能多余重订阅(eslint 常提示)。


3. 与 Context 的对比

ContextZustand + useSyncExternalStore
更新传播Provider value 变 → 消费者常全刷仅 selector 切片变才刷
样板Provider 包裹无 Provider
测试注入换 Provider value需自建 Context 包 store 或 mock 模块

4. create 与 Store 实例

  • 每个 create(...) 产生独立 store 单例(模块级 const)。
  • 同一文件导出 useBearStore 即全局共享;多实例需多次 create 或 Vanilla + Context 注入。

5. 并发相关(延伸阅读)


6. 总结

React 集成层极薄:不重新发明订阅,而是把现有 subscribe/getState 交给 React 官方外部 store Hook。性能与正确性主要取决于 选择器粒度快照引用稳定07-性能优化)。

MIT License.