Zustand 拥有一个免费状态管理器,可在 10 行代码中取代 Redux
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 的可变更新。
功能比较
| 特性 | Zustand | Redux Toolkit | Jotai | Recoil |
|---|---|---|---|---|
| 体积大小 | ~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 提供了一个轻量级的替代方案,同时不牺牲功能。