React-Spring/Zustand 状态管理:自动生成选择器指南
zustand 项目地址: https://gitcode.com/gh_mirrors/zus/zustand
什么是 Zustand 选择器?
在 Zustand 状态管理库中,选择器(selector)是一种从存储(store)中提取特定状态或操作的函数。它允许组件只订阅它们真正需要的状态部分,而不是整个存储,这对于性能优化非常重要。
为什么需要自动生成选择器?
手动编写选择器虽然直观,但当存储中有大量状态和操作时,会变得重复且繁琐。例如:
const bears = useBearStore((state) => state.bears);
const increment = useBearStore((state) => state.increment);
对于大型应用,这种写法会导致大量重复代码。自动生成选择器可以解决这个问题,让代码更简洁、更易维护。
如何实现自动选择器生成
核心实现原理
自动生成选择器的核心思路是通过遍历存储的状态键,为每个键创建一个对应的选择器函数。这利用了 TypeScript 的类型系统和 Zustand 的 API。
实现代码解析
以下是实现自动选择器生成的核心函数:
import { StoreApi, UseBoundStore } from 'zustand';
type WithSelectors<S> = S extends { getState: () => infer T }
? S & { use: { [K in keyof T]: () => T[K] } }
: never;
const createSelectors = <S extends UseBoundStore<StoreApi<object>>>(
_store: S,
) => {
let store = _store as WithSelectors<typeof _store>;
store.use = {};
for (let k of Object.keys(store.getState())) {
(store.use as any)[k] = () => store((s) => s[k as keyof typeof s]);
}
return store;
};
这个函数做了以下几件事:
- 定义了一个类型
WithSelectors
,它将原始存储类型扩展为包含一个use
对象 - 遍历存储中的所有状态键
- 为每个键创建一个选择器函数,并添加到
use
对象中
使用示例
假设我们有一个简单的熊状态存储:
interface BearState {
bears: number;
increase: (by: number) => void;
increment: () => void;
}
const useBearStoreBase = create<BearState>()((set) => ({
bears: 0,
increase: (by) => set((state) => ({ bears: state.bears + by })),
increment: () => set((state) => ({ bears: state.bears + 1 })),
}));
应用自动选择器生成:
const useBearStore = createSelectors(useBearStoreBase);
现在可以这样使用:
// 获取状态
const bears = useBearStore.use.bears();
// 调用操作
const increment = useBearStore.use.increment();
非 React 环境下的实现
如果你在非 React 环境中使用 Zustand 的纯存储(vanilla store),可以使用以下变体:
import { StoreApi, useStore } from 'zustand';
const createSelectors = <S extends StoreApi<object>>(_store: S) => {
const store = _store as WithSelectors<typeof _store>;
store.use = {};
for (const k of Object.keys(store.getState())) {
(store.use as any)[k] = () =>
useStore(_store, (s) => s[k as keyof typeof s]);
}
return store;
};
使用方法与 React 版本类似。
类型安全考虑
自动生成的选择器保持了完整的 TypeScript 类型支持。当你访问 useBearStore.use.bears()
时,TypeScript 知道返回值是 number
类型;访问 useBearStore.use.increment()
时,知道返回值是 () => void
类型。
性能优化
虽然自动生成选择器很方便,但要注意:
- 每个选择器都会创建一个新的订阅
- 对于大型状态对象,自动生成的选择器可能会创建不必要的订阅
- 在性能敏感的场景中,可能需要手动创建优化的选择器
实际应用建议
- 中小型状态:自动选择器非常适合中小型状态管理
- 大型状态:考虑手动创建选择器或按功能模块拆分存储
- 性能关键路径:在性能关键组件中,使用手动优化的选择器
总结
自动生成选择器是 Zustand 状态管理中的一个强大模式,它可以显著减少样板代码,提高开发效率。通过本文介绍的方法,你可以轻松地为你的 Zustand 存储添加自动选择器功能,同时保持类型安全和良好的开发体验。
对于大多数应用场景,自动生成选择器是一个值得采用的实践,它让状态管理代码更加简洁、更易维护。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考