Zustand 源码阅读心得
一、引言
- 背景动机
为什么选择阅读 Zustand 源码?(轻量、设计思想、性能优化等) - 阅读目标
理解状态管理核心机制、学习设计模式、探究性能优化策略 - 库简介
Zustand 的核心定位:轻量级、不可变、基于 Hook 的状态管理
二、核心概念剖析
1. 关键设计思想
- 单一全局 Store 与多 Store 模式
- 不可变更新模式(Immer 集成)
- 细粒度响应式更新(状态切片订阅)
- 中间件机制(Redux 兼容、持久化、日志等)
2. 核心 API 分析
createStore()的创建流程useStoreHook 的内部依赖追踪create函数
三、关键源码解析
1. Store(Vanilla Store) 创建过程
// 示例代码片段 + 分析
function createStoreImpl(createState) {
let state; // 当前状态闭包存储
const listeners = new Set(); // 订阅者集合
const setState = (partial, replace) => {
// 状态合并逻辑...
// 通知所有订阅者
listeners.forEach((listener) => listener(state, previousState));
};
const getState = () => state;
const subscribe: StoreApi<TState>['subscribe'] = (listener) => {
listeners.add(listener);
// Unsubscribe
return () => listeners.delete(listener);
};
const api = { setState, getState, getInitialState, subscribe };
return api as any;
}
export const createStore = ((createState) =>
createState ? createStoreImpl(createState) : createStoreImpl) as CreateStore;
核心就是createStoreImpl这个函数,执行完后到这一步基本就是一个存储状态+支持订阅的对象
2. useStore Hook 依赖追踪
// 示例代码片段 + 分析
// selector为undefined 时默认快照函数返回整个store状态
const identity = <T>(arg: T): T => arg;
export function useStore<TState, StateSlice>(
api: ReadonlyStoreApi<TState>, // Vanilla Store
selector: (state: TState) => StateSlice = identity as any,
) {
// useSyncExternalStore 订阅外部store的hook
// 接收三个参数
// 第一个参数:订阅函数,返回一个取消订阅函数
// 第二个参数:获取快照函数
// 第三个参数:获取服务器端快照函数(可选)
// 返回值:根据快照函数返回值
// 作用:监听store变化,当store变化时,根据快照函数返回值比较确定发生了变化,react就重新渲染组件
const slice = React.useSyncExternalStore(
api.subscribe,
() => selector(api.getState()),
() => selector(api.getInitialState()),
);
return slice;
}
useStore这一函数通过useSyncExternalStore这一hook实现对store的订阅,当store变化时,react就重新渲染组件。
即Vanilla Store通过useStore成了受react控制的状态
3. create 函数
export const create = (<T>(createState: StateCreator<T, [], []> | undefined) =>
createState ? createImpl(createState) : createImpl) as Create;
const createImpl = <T>(createState: StateCreator<T, [], []>) => {
const api = createStore(createState); // 本质上也是要先创建Vanilla Store
const useBoundStore: any = (selector?: any) => useStore(api, selector); // 外部调用useBoundStore === 执行useStore使状态具备响应式
Object.assign(useBoundStore, api);
return useBoundStore;
};
因此可以说明:create = createStore + useStore
4. create和createStore选择总结
| 场景 | 使用的 API | 说明 |
|---|---|---|
| React 组件 | create | 直接生成 React Hook,开箱即用 |
| 非 React 环境 | createStore | 创建框架无关的原始 Store |
| 混合使用 | createStore + useStore | 在 React 外创建 Store,再手动绑定到组件 |
💡 最佳实践:
-
优先用 create 开发 React 应用(更简洁)。
-
仅当需要脱离 React 操作状态时(如通用库、SSR、全局监听),才用 createStore。