React-Spring/Zustand 状态管理:自动生成选择器指南

React-Spring/Zustand 状态管理:自动生成选择器指南

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;
};

这个函数做了以下几件事:

  1. 定义了一个类型 WithSelectors,它将原始存储类型扩展为包含一个 use 对象
  2. 遍历存储中的所有状态键
  3. 为每个键创建一个选择器函数,并添加到 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 类型。

性能优化

虽然自动生成选择器很方便,但要注意:

  1. 每个选择器都会创建一个新的订阅
  2. 对于大型状态对象,自动生成的选择器可能会创建不必要的订阅
  3. 在性能敏感的场景中,可能需要手动创建优化的选择器

实际应用建议

  1. 中小型状态:自动选择器非常适合中小型状态管理
  2. 大型状态:考虑手动创建选择器或按功能模块拆分存储
  3. 性能关键路径:在性能关键组件中,使用手动优化的选择器

总结

自动生成选择器是 Zustand 状态管理中的一个强大模式,它可以显著减少样板代码,提高开发效率。通过本文介绍的方法,你可以轻松地为你的 Zustand 存储添加自动选择器功能,同时保持类型安全和良好的开发体验。

对于大多数应用场景,自动生成选择器是一个值得采用的实践,它让状态管理代码更加简洁、更易维护。

zustand zustand 项目地址: https://gitcode.com/gh_mirrors/zus/zustand

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梅研芊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值