zustand 源码解析
此文章基于 zustand v4.3.8
zustand 的4.3.8 tags 链接, zustand 的文档地址
使用方式
zustand是基于发布订阅模式实现的一个状态管理库,可以不局限于仅在react项目中使用,不过对react的支持是官方实现的,使用起来也非常简洁,使用示例如下
- js
- ts
// 在js项目中使用,不需要类型
import { create } from "zustand";
const initStateCreateFunc = (set) => ({
bears: 0,
increase: (by) => set((state) => ({ bears: state.bears + by })),
});
const useBearStore = create(initStateCreateFunc);
// ts项目,需要类型提示
import { create } from "zustand";
interface BearState {
bears: number;
increase: (by: number) => void;
}
const initStateCreateFunc = (set) => ({
bears: 0,
increase: (by) => set((state) => ({ bears: state.bears + by })),
});
const useBearStore = create<BearState>()(initStateCreateFunc);
如上文代码,在调用create函数后,会生成一个useStore的 hook,这个 hook 基本的使用方式和redux的useSelector的一模一样
function BearCounter() {
const bears = useBearStore((state) => state.bears);
return <h1>{bears} around here...</h1>;
}
function Controls() {
const increase = useBearStore((state) => state.increase);
return <button onClick={increase}>one up</button>;
}
细心地你可能发现 js 和 ts 的使用有不同,ts 是 create<BearState>()(initStateCreateFunc),原因会在下文解释
源码主体流程
zustand的核心是将外部store和组件view的交互,交互的核心流程如下图

先使用create函数基于注入的initStateCreateFunc创建一个闭包的store,并暴露对应的subscribe、setState、getState、(此 api 将被移除)这几个destoryapi
借助于react官方提供的useSyncExternalStoreWithSelector可以将store和view层绑定起来,从而实现使用外部的store来控制页面的展示。
zustand还支持了middleware的能力,采用create(middleware(...args))的形式即可使用对应的middleware
核心代码详解
这部分讲解最核心的create和useSyncExternalStoreWithSelector函数
create 函数生成 store
为了便于阅读,代码有删减
前置知识介绍
create函数生成的store是一个闭包,通过暴露api的方式实现对store的访问。
核心代码在vanilla.ts和react.ts这两个文件中,vanilla.ts里实现了一个完整的有pub-sub能力的store, 不需要依赖于react即可使用。
react.ts里基于useSyncExternalStoreWithSelector实现了一个useStore的 hook,在组件里调用create返回的函数时会将store和组件绑定起来,而这个绑定就是useStore实现的
这个useSyncExternalStoreWithSelector会在下一小节讲述。