Mini State Store¶
从 569 行的
src/state/AppStateStore.ts提炼到 ~60 行 的useSyncExternalStore模式。 5 个测试场景:基本 / 订阅 / Selector / 同 ref 不通知 / React 集成。
文件¶
mini-state-store/
├── src/
│ ├── store.ts Store 类 + createSyncExternalStore polyfill(~60 行)
│ └── cli.ts 5 测试场景(~100 行)
└── README.md
跑¶
真实代码对照¶
| Demo | 真实文件 | 简化 |
|---|---|---|
Store |
AppStateStore.ts:30 (~200 行) |
60 行 |
subscribeWithSelector |
AppStateStore.ts:400 (~150 行) |
8 行(带 equality) |
createSyncExternalStore |
React 18 useSyncExternalStore polyfill | 3 方法 |
核心 4 件套¶
1️⃣ 三件套 API¶
class Store<T> {
getState(): T // 读
setState(next | (s)=>next) // 写
subscribe(listener): ()=>void // 订阅(返 unsubscribe)
}
2️⃣ Same-ref 不通知¶
setState(next) {
if (next === this.state) return; // ← 关键优化
this.state = next;
this.listeners.forEach((l) => l(this.state));
}
3️⃣ Selector 订阅(精细粒度)¶
subscribeWithSelector(
selector: (state) => U, // 选哪部分
listener: (selected, prev) => void,
equalityFn: Object.is, // 默认 Object.is
)
state.user.name 时,state.user.age 变了不通知。
4️⃣ React useSyncExternalStore 集成¶
React 18 提供的 hook,专门订阅外部 store。本 demo 的 createSyncExternalStore 返回 3 个方法:
- getSnapshot() —— 同步取当前 state(React 在 render 时调)
- subscribe(onStoreChange) —— 订阅 + 通知 React
- getServerSnapshot() —— SSR 用,避免 hydration mismatch
测试输出¶
📌 Test 1: Basic getState / setState
initial: {"count":0,"user":null,"theme":"light"}
📌 Test 2: subscribe() listener
[listener] value changed: 1
[listener] value changed: 2
📌 Test 3: subscribeWithSelector() with equality
(age changed but name same: NOT notified)
[selector] name: Alice → Bob
📌 Test 4: setState same ref = no notify
notified 2 times
📌 Test 5: useSyncExternalStore integration
React would re-render 2 times
进阶练习¶
- 加 middleware:logger / devtools / persistence / undo
- 加 immer:自动深拷贝 + 结构共享
- 加 time-travel debug:记录所有 state 历史,支持回放
- 加 batch updates:用 React 18 的
unstable_batchedUpdates合并多次 setState - 加 async action:dispatch(asyncFn) 支持 thunk
- 加 selector memoization:用 reselect 缓存 selector 结果
相关阅读¶
- topics/deep-dive-store.md —— 569 行完整分析
- phase-03-state.md —— 状态管理 7 阶段
- React useSyncExternalStore 文档
- Zustand 源码 —— 用本模式实现的库
- Jotai 源码 —— atomic state