前言 :在 React 的世界里,如果说组件(Component)是勤勤恳恳工作的公民,那么状态(State)就是流动的货币。当应用规模扩大,仅仅靠父子组件间的"现金交易"(Props drilling)已经无法维持经济系统的运转。我们需要一个中央银行,一个专业的财务管理部门。
今天,我们不谈繁琐的 Redux,而是聊聊 Zustand ------ 这个来自德国的"小而美"的状态管理库,看看它是如何通过极其精简的 API,帮我们把"企业做大做强"的。
一、 为什么我们需要"中央银行"?
我们在写 React 组件时,心中的公式往往是:
<math xmlns="http://www.w3.org/1998/Math/MathML"> U I = f ( S t a t e ) UI = f(State) </math>UI=f(State)
但在实际开发中,如果不引入全局状态管理,我们面临着几个痛点:
- 层级地狱:想要把孙子的状态传给爷爷,Props 需要传递数层。
- 兄弟失联:兄弟组件之间无法直接通信,状态必须提升(Lifting State Up)到共同父级,导致不必要的重渲染。
"企业做大做强,请管理财务、状态以及修改状态的规矩。"
Zustand 就是这样一个基于 Hooks 思想实现的中央管理系统。它将状态存入 Store(仓库),实现全局共享,且不需要在最外层包裹繁琐的 Provider。
二、 建立你的第一家"分行":基础状态管理
让我们从最简单的计数器开始。在 Zustand 中,创建一个 Store 就像开一家分店一样简单。
1. 定义规矩(Interface)与 存储(Store)
在"企业管理"中,不仅要有钱(Count),还要有动用这笔钱的规矩(Actions)。
TypeScript
typescript
// store/counter.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
// 1. 定义账本的结构:即使是小钱,也要有类型约束
interface CounterState {
count: number;
increment: () => void;
decrement: () => void;
reset: () => void;
}
// 2. 创建金库,并制定修改规则
export const useCounterStore = create<CounterState>()(
persist( // 使用中间件,相当于给金库加了把"永久保存"的锁
(set) => ({
// 列出资产(状态)
count: 0,
// 状态要怎么改?必须通过合法的手段(Action)
// set 函数是 Zustand 的核心,它是唯一合法的修改器
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 }),
}),
{
name: 'counter-storage', // 存到 localStorage 里的名字
}
)
);
核心解读:
create: 建立仓库。set: 这是唯一的"财务审批笔"。你不能直接state.count++,必须通过set返回一个新的对象。这保证了数据的不可变性(Immutability) 。persist: 这是 Zustand 的杀手锏中间件。它自动将状态同步到localStorage,刷新页面数据不丢失。
三、 处理复杂资产:对象与数组的不可变性
当我们的资产不仅仅是数字,而是复杂的待办事项列表(TodoList)或用户信息(User)时,不可变性的操作显得尤为重要。
1. Todo List 的增删改查
在 useTodoStore 中,我们看到了数组操作的标准范式:
TypeScript
typescript
// store/todo.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type { Todo } from '../types';
export interface TodoState {
todos: Todo[];
addTodo: (text: string) => void;
toggleTodo: (id: number) => void;
removeTodo: (id: number) => void;
}
export const useTodoStore = create<TodoState>()(
persist(
(set) => ({
todos: [],
// 新增:利用解构 [...old, new] 创建新数组
addTodo: (text: string) =>
set((state) => ({
todos: [...state.todos, {
id: Date.now(),
text,
completed: false
}]
})),
// 切换状态:利用 map 生成新数组,不修改原对象
toggleTodo: (id: number) =>
set((state) => ({
todos: state.todos.map((todo) =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
)
})),
// 删除:利用 filter 过滤
removeTodo: (id: number) =>
set((state) => ({
todos: state.todos.filter(todo => todo.id !== id)
})),
}),
{ name: 'todos-storage' }
)
);
深度思考:
这里的 map、filter 和展开运算符 ... 不是为了炫技,而是为了配合 React 的更新机制。React 依赖引用的变化来感知更新,如果我们直接 todos.push(),引用不变,UI 就不会刷新。这就是"修改状态的规矩" 。
2. 用户鉴权状态
同样的逻辑适用于用户信息管理:
TypeScript
typescript
// store/user.ts
interface UserState {
isLoggin: boolean;
user: User | null;
login: (user: User) => void;
logout: () => void;
}
// ... 代码省略,逻辑同上,利用 set 同时更新多个字段
四、 消费状态:在 UI 组件中提款
有了银行(Store),组件(App.tsx)就可以轻松地存取数据了。Zustand 的 Hook API 让这一切变得像使用 useState 一样自然。
TypeScript
javascript
// App.tsx
import { useCounterStore } from './store/counter';
import { useTodoStore } from './store/todo';
function App() {
// 1. 直接提取所需的 State 和 Actions
// 就像从 ATM 取钱一样简单
const { count, increment, decrement, reset } = useCounterStore();
const { todos, addTodo, toggleTodo, removeTodo } = useTodoStore();
// 2. 结合本地 UI 逻辑 (Input value)
const [inputValue, setInputValue] = useState("");
const handleAdd = () => {
if (!inputValue.trim()) return;
addTodo(inputValue); // 调用 Store 的 Action
setInputValue("");
}
return (
<div>
{/* UI 渲染逻辑,完全解耦 */}
<h1>Count: {count}</h1>
<button onClick={increment}>+1</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{/* 这里的 toggleTodo 直接来自 Store */}
<span onClick={() => toggleTodo(todo.id)}>
{todo.text}
</span>
</li>
))}
</ul>
</div>
)
}
五、 总结:Zustand 的企业级管理哲学
回到开头提到的代码注释: "专业管理状态,修改状态的规矩" 。
Zustand 相比于其他工具,胜在平衡:
- 极简主义 :没有 Boilerplate(样板代码),没有
Provider包裹,即装即用。 - 规矩严明 :通过 TypeScript 接口定义
State,通过Actions封装修改逻辑。组件只负责"触发",Store 负责"执行"。 - 持久化 :
persist中间件让数据存储变得透明化。
如果把 React 应用比作一家公司,useState 是员工口袋里的零花钱,而 Zustand 就是那个高效、透明且严格执行财务制度的财务部。