Zustand 拥有一个免费状态管理器,可在 10 行代码中取代 Redux

发布: (2026年3月30日 GMT+8 02:10)
4 分钟阅读
原文: Dev.to

Source: Dev.to

Redux 通常需要 actions、reducers、selectors、middleware,甚至对于一个简单的计数器也要写上百行样板代码。
Zustand 只需几行代码即可实现相同的功能——无需 actions、reducers、dispatchers 或 Provider 组件。

最小化 API

  • 在几行代码中创建 store,并可在任何地方使用。
  • 无需样板代码——不需要 actions、reducers 或 context providers。
  • 无需 <Provider> 包装器——只需导入 hook。
  • TypeScript 优先——开箱即用的完整类型。
  • 内置中间件支持(persist、devtools、immer、subscriptions)。
  • gzipped 大约 1 KB(相较于 Redux Toolkit 的约 30 KB)。

安装

npm install zustand

计数器示例

import { create } from 'zustand';

interface CounterStore {
  count: number;
  increment: () => void;
  decrement: () => void;
  reset: () => void;
}

const useCounter = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}));

// Any component can import and use the store directly
function Counter() {
  const count = useCounter((state) => state.count);
  const increment = useCounter((state) => state.increment);

  return (
    <div>
      Count: {count}
      <button onClick={increment}>+</button>
    </div>
  );
}

无需 <Provider> 包装器,无需 connect(),也无需 useSelector/useDispatch

带持久化的 Auth Store

import { create } from 'zustand';
import { persist } from 'zustand/middleware';

interface User {
  id: string;
  name: string;
  email: string;
}

interface AuthStore {
  user: User | null;
  token: string | null;
  login: (email: string, password: string) => Promise;
  logout: () => void;
  isAuthenticated: () => boolean;
}

const useAuth = create()(
  persist(
    (set, get) => ({
      user: null,
      token: null,

      login: async (email, password) => {
        const { user, token } = await api.login(email, password);
        set({ user, token });
      },

      logout: () => set({ user: null, token: null }),

      isAuthenticated: () => get().token !== null,
    }),
    { name: 'auth-storage' } // Persists to localStorage
  )
);

Todo Store(异步操作)

import { create } from 'zustand';

interface Todo {
  id: string;
  title: string;
  done: boolean;
}

interface TodoStore {
  todos: Todo[];
  loading: boolean;
  fetchTodos: () => Promise;
  addTodo: (title: string) => Promise;
  toggleTodo: (id: string) => void;
}

const useTodos = create((set, get) => ({
  todos: [],
  loading: false,

  fetchTodos: async () => {
    set({ loading: true });
    const todos = await api.getTodos();
    set({ todos, loading: false });
  },

  addTodo: async (title) => {
    const todo = await api.createTodo({ title });
    set((state) => ({ todos: [...state.todos, todo] }));
  },

  toggleTodo: (id) => {
    set((state) => ({
      todos: state.todos.map((t) =>
        t.id === id ? { ...t, done: !t.done } : t
      ),
    }));
  },
}));

异步逻辑使用普通的 async/await 编写;无需 createAsyncThunk 或额外的中间件。

中间件堆栈示例

import { create } from 'zustand';
import { devtools, persist, immer } from 'zustand/middleware';

interface Store {
  items: string[];
  addItem: (item: string) => void;
}

const useStore = create()(
  devtools(
    persist(
      immer((set) => ({
        items: [],
        addItem: (item) =>
          set((state) => {
            state.items.push(item); // Immer makes this mutable update safe
          }),
      })),
      { name: 'my-store' }
    )
  )
);

结合了 Redux DevTools 支持、localStorage 持久化以及基于 Immer 的可变更新。

功能比较

特性ZustandRedux ToolkitJotaiRecoil
体积大小~1 KB~30 KB~3 KB~20 KB
样板代码最少中等最少中等
需要 Provider
异步处理内置createAsyncThunk内置选择器
开发者工具内置插件内置插件
学习曲线~5 min~1 hour~15 min~30 min
TypeScript 支持优秀良好优秀良好

TL;DR

Zustand 是一种状态管理方案,适合想要 零仪式感 的开发者:体积小、无需 Provider、无需 reducers,且提供简单、类型安全的 API。如果 Redux 对你的项目来说显得笨重,Zustand 提供了一个轻量级的替代方案,同时不牺牲功能。

0 浏览
Back to Blog

相关文章

阅读更多 »