Skip to Content
ToolsZustand 工具

Zustand 工具

一个基于 zustand 的状态管理工具,它简化了 zustand 的使用方式,并提供了更好的类型支持和性能优化。

基本用法

创建 Store

使用 createStore 函数来创建一个 store,它接收一个配置对象,包含 stateactions 两个字段:

import { createStore } from "@next-tools/tools/zustand"; const store = createStore({ state: { count: 0, user: { name: "John" }, }, actions: { increment: (state, amount: number) => { state.count += amount; }, setUserName: (state, name: string) => { state.user.name = name; }, }, });

配置说明

  • state: 定义初始状态,必须是一个对象
  • actions: 定义修改状态的方法,每个方法接收两个参数:
    • state: 当前状态,可以直接修改(基于 immer)
    • payload: 方法的参数

状态管理

获取状态

// 获取完整状态 const state = store.getState(); // 在 React 组件中使用 const count = store.useSnapshot((state) => state.count);

修改状态

// 使用 actions store.actions.increment(1); store.actions.setUserName("Jane");

React 集成

useSnapshot vs useShallowSnapshot

useSnapshot

useSnapshot 用于在组件中订阅状态变化:

function Counter() { // 订阅完整状态 const state = store.useSnapshot(); // 使用选择器只订阅部分状态 const count = store.useSnapshot(s => s.count); return <div>{count}</div>; }

useShallowSnapshot

useShallowSnapshot 用于性能优化,它会对选择器返回的值进行浅层比较来减少不必要的重渲染:

function UserInfo() { // 只有当返回的对象经过浅比较后发生变化时才会重渲染 // 例如:user.name 改变会导致返回新的对象,触发重渲染 const user = store.useShallowSnapshot(s => s.user); return <div>{user.name}</div>; }

最佳实践

  1. 使用选择器获取状态:
// ✅ 好的做法:只订阅需要的状态 const count = store.useSnapshot((s) => s.count); // ❌ 避免订阅整个状态:可能导致不必要的重渲染 const state = store.useSnapshot();
  1. 合理使用 useShallowSnapshot:
// ✅ 返回对象时使用 useShallowSnapshot const userInfo = store.useShallowSnapshot((s) => ({ name: s.user.name, age: s.user.age, })); // ❌ 返回原始类型时不要使用 useShallowSnapshot const count = store.useShallowSnapshot((s) => s.count); // 没有优化效果

性能优化

手动优化

  1. 使用选择器减少重渲染:
// 只有 count 变化时重渲染 const count = store.useSnapshot((s) => s.count);
  1. 对象类型使用 useShallowSnapshot:
// 只有 user 对象引用变化时重渲染 const user = store.useShallowSnapshot((s) => s.user);
  1. 避免频繁的状态更新:
// ✅ 批量更新 store.actions.updateUser({ name: "Jane", age: 25, }); // ❌ 避免多次更新 store.actions.setName("Jane"); store.actions.setAge(25);

自动优化示例

通过 Babel 插件,我们提供了自动优化功能,可以在编译时自动优化状态访问模式。以下是两个主要的优化场景:

1. 解构语法优化

编译前的代码:

function UserProfile() { // 直接解构会订阅整个状态 const { user, settings } = store.useSnapshot(); return ( <div> <h1>{user.name}</h1> <p>{settings.theme}</p> </div> ); }

编译后的代码:

function UserProfile() { // 自动生成选择器函数,只订阅需要的字段 const selector = (state) => ({ user: state.user, settings: state.settings }); // 使用 useShallowSnapshot 优化性能 const { user, settings } = store.useShallowSnapshot(selector); return ( <div> <h1>{user.name}</h1> <p>{settings.theme}</p> </div> ); }

2. 属性访问优化

编译前的代码:

function Counter() { // 订阅了整个状态 const state = store.useSnapshot(); return ( <div> <p>Count: {state.count}</p> <p>Total: {state.total}</p> </div> ); }

编译后的代码:

function Counter() { // 自动生成选择器函数,只订阅使用到的字段 const selector = (state) => ({ count: state.count, total: state.total }); // 转换为使用选择器的形式 const state = store.useSnapshot(selector); return ( <div> <p>Count: {state.count}</p> <p>Total: {state.total}</p> </div> ); }

这些优化会在编译时自动应用,无需手动编写选择器函数。通过自动生成选择器和使用 useShallowSnapshot,可以有效减少不必要的重渲染,提高应用性能。

类型支持

store 的类型会自动推导:

const store = createStore({ state: { count: 0 }, actions: { increment: (state, amount: number) => { state.count += amount; }, }, }); // ✅ 类型安全 store.actions.increment(1); // ❌ 类型错误 store.actions.increment("1"); // Type 'string' is not assignable to type 'number'