使用 Zustand 优化 React 状态管理:性能与持久化实践

584 阅读4分钟

在 React 项目中,状态管理是一个核心问题。传统的状态管理工具,如:Redux 或者 MobX,虽然功能强大,但是使用不当会引入复杂性和性能问题。而 Zustand 是一个轻量级的状态管理库,以简单、高效和灵活著称,尤其是在性能优化方面表现出色。本文讲结合 QueryBox 项目中的实际使用案例,介绍 Zustand 的优势、工作原理以及自定义持久化方案。

为什么选择 Zustand?

Zustand 的核心设计理念是简单和高效,有以下优势:

  1. 轻量级:Zustand 的核心库非常小,不会对项目体积造成负担。
  2. 没有样板代码:相比 Redux,Zustand 没有复杂的 action、reducer 和 middleware,开发者可以直接定义状态和操作。
  3. 性能优化:Zustand 内置了字段级别的细粒度订阅机制,可以避免不必要的组件重渲染。
  4. 灵活性:支持多种状态管理模式,包括全局状态、局部状态和异步状态。

Zustand 的性能优化原理

Zustand 的性能优化主要体现在以下几个方面:

  • 细粒度的订阅机制

Zustand 的状态存储是基于订阅的,组件只会订阅它实际使用的状态片段,而不是整个状态树。这意味着当状态更新时,只有依赖该状态的组件会重新渲染,而其他组件不会收到影响。

举个例子,在项目中,我们可以看到类似的实现:

源码在:🔗 点击跳转到文件

export const useThemeModeStore = create<ThemeModeStore>()(
  persist(
    (set) => ({
      themeMode: 'system',
      resolvedThemeMode: 'light',
      setThemeMode: (themeMode) => set(() => ({ themeMode })),
    }),
    {
      name: 'theme-mode',
      storage: createSettingsStorage<ThemeModeStoreState>({
        valueKey: 'themeMode',
        upsertOptions: {
          value_type: SettingsValueTypes.STRING,
          category: SettingsCategories.UI_THEME,
        },
      }),
    }
  )
)

在这个例子中,useThemeModeStore 只会触发与 themeModeresolvedThemeMode 相关的组件更新,而不会影响其他状态。

  • 避免不必要的状态拷贝

Zustand 使用了浅拷贝的方式更新状态,避免了深拷贝带来的性能开销。开发者可以直接通过 set 方法更新状态,而不需要手动合并状态。

set((state) => ({
  ...state,
  appSidebarCollapsed: collapsed,
}))
  • 支持选择性订阅

Zustand 提供了 zustand/subscribeWithSelector 中间件,允许组件只订阅状态的某些部分。例如:

useAppSidebarMenuStore.subscribe(
  (state) => state.activeItemKey,
  (activeItemKey) => {
    console.log('Active item key changed:', activeItemKey)
  }
)

通过选择性订阅,开发者可以进一步减少不必要的渲染。

Zustand 的持久化方案

在项目中,我们使用了 Zustand 的 persist 中间件来实现状态的持久化。持久化的状态会存储在浏览器的 localStorage 或其他存储介质中,即使页面刷新也能保持状态。

持久化的实现

以下是一个持久化状态的示例:

export const useAppSidebarCollapsedStore = create<AppSidebarCollapsedStore>()(
  persist(
    (set) => ({
      appSidebarCollapsed: false,
      setAppSidebarCollapsed: (collapsed: boolean) =>
        set({ appSidebarCollapsed: collapsed }),
    }),
    {
      name: SettingsKeys.UI.SIDEBAR.COLLAPSED,
      storage: createSettingsStorage<AppSidebarCollapsedStoreState>({
        valueKey: 'appSidebarCollapsed',
        upsertOptions: {
          value_type: SettingsValueTypes.BOOLEAN,
          category: SettingsCategories.APP_SIDEBAR,
          description: 'App sidebar collapsed status',
        },
      }),
    }
  )
)

在这个例子中,我们通过 persist 中间件将 appSidebarCollapsed 状态持久化到存储中。createSettingsStorage 是一个自定义的存储适配器,用于与项目的设置存储系统集成。

自定义存储适配器

项目中实现了一个通用的存储适配器 createSettingsStorage,它支持将 Zustand 的状态与后端存储系统同步:

export function createSettingsStorage<T extends object>(
  options: SettingsStorageOptions<T>
) {
  // 自定义存储逻辑
}

具体的实现可以参考:github.com/zhnd/query-…

这种方式不仅支持本地存储,还可以扩展到远程存储(如数据库),实现更复杂的状态管理需求。

总结

Zustand 是一个轻量级、高性能的状态管理工具,特别适合需要细粒度状态管理的 React 项目。通过其细粒度的订阅机制和简单的 API,Zustand 能够显著减少不必要的组件重渲染,从而提升应用性能。

此外,Zustand 的 persist 中间件为状态持久化提供了便捷的解决方案,结合自定义存储适配器,可以满足多种存储需求。

在实际项目中,Zustand 的灵活性和高效性让我们能够更专注于业务逻辑,而不是被复杂的状态管理工具束缚。如果你正在寻找一个简单、高效的状态管理工具,不妨试试 Zustand!