别再用 Redux 写三个文件了,Zustand 一行搞定!

85 阅读3分钟

别再用 Redux 写三个文件了,Zustand 一行搞定!

Zustand 是一个专为 React 应用设计的状态管理库,其核心目标是简化状态共享和管理,同时保持高性能和良好的可维护性。它以轻量、直观、可扩展著称,适合各种规模的 React 项目。

一、Zustand 的使用

  1. 安装

    首先确保你已经安装了 React,然后安装 Zustand:

    npm install zustand
    

    或者使用 yarn:

    yarn add zustand
    
  2. 创建 Store

    Zustand 使用 create 函数创建一个全局的可响应状态容器(store)。

    import {
      create, // 创建一个store 存储状态的地方
    } from "zustand";
    
    export const useCounterStore = create((set) => ({
      // 状态 + 修改状态的方法
      count: 0,
      increment: () => {
        set((state) => ({ // state 是上一个状态对象
          count: state.count + 1,
        }));
      },
      discrement: () => {
        set((state) => ({ count: state.count - 1 }));
      },
    }));
    
    
    • set 是用于更新状态的核心函数。
    • 状态和方法都可以放在 store 中,形成一个“单一状态树”。
    • useStore 是一个自定义 Hook,可以用于组件中访问状态。
  3. 在组件中使用 Store

    import { useCounterStore } from "@/store/count";
    
    function App() {
      const { count } = useCounterStore();
      return (
        <>
          <h2>App: {count}</h2>
          <Counter />
        </>
      );
    }
    
    const Counter = () => {
      const { count, increment, discrement } = useCounterStore();
      return (
        <div>
          <h2>Counter: {count}</h2>
          <button onClick={increment}>+</button>
          <button onClick={discrement}>-</button>
        </div>
      );
    };
    
    • 使用 useStore Hook 可以获取状态和更新方法。
    • Zustand 会自动追踪依赖,只有使用了相关状态的组件才会重新渲染。
  4. 异步操作

    Zustand 支持异步操作,可以在 store 中定义异步函数:

    const useStore = create((set) => ({
      data: null,
      loading: false,
      error: null,
      fetchData: async () => {
        set({ loading: true });
        try {
          const response = await fetch('https://api.example.com/data');
          const result = await response.json();
          set({ data: result, loading: false });
        } catch (err) {
          set({ error: err.message, loading: false });
        }
      },
    }));
    

    在组件中调用:

    const { data, loading, error, fetchData } = useStore();
    
    useEffect(() => {
      fetchData();
    }, [fetchData]);
    

二、Zustand 的使用注意事项

  1. 状态更新是异步的(使用 immer 时除外)

    Zustand 的 set 方法默认是浅合并(shallow merge),因此更新状态时要避免直接修改原状态对象。推荐使用函数式更新:

    set((state) => ({ count: state.count + 1 }));
    
  2. 避免在 store 中保存大量数据

    虽然 Zustand 支持复杂状态,但不要将大型数据结构(如大数组、嵌套对象)直接放在 store 中。建议:

    • 将数据分片存储
    • 使用 selector 模式访问部分状态,避免不必要的渲染
  3. 多个 Store 的管理

    Zustand 支持创建多个 store,适合模块化管理状态:

    const useUserStore = create(...);
    const useCartStore = create(...);
    

    如果多个 store 之间需要通信,可以考虑:

    • 在组件中组合多个 store
    • 使用中间件或全局事件进行通信
  4. 性能优化建议

  • 使用 selector 模式:通过 useStore(selector) 只监听部分状态,避免不必要的组件重渲染。
const count = useStore((state) => state.count);
  • 避免频繁创建 store:store 应该在应用初始化时创建一次,而不是每次渲染都重新创建。
  • 合理使用中间件:如 devtools、persist 等,避免过度使用影响性能。

三、Zustand 的思想理念

Zustand 的设计哲学可以总结为以下几点:

  • 体积小(压缩后仅 1KB 左右),对性能影响极小。使用高效的响应式更新机制,仅更新依赖状态的组件。

  • 完全基于 React 的 Hook API 构建。支持 Suspense、Server Components、Next.js 等现代 React 特性。与 React Query、TanStack Router 等现代 React 工具完美集成。

  • 支持中间件系统,可扩展 DevTools、持久化、日志记录等功能。可与 Immer、Redux DevTools、localStorage 等工具无缝集成。

  • 不需要编写大量模板代码(如 action creators、reducers)。不需要将组件包裹在 Provider 中。更加符合现代 React 开发习惯。