03-状态管理与路由——03. Zustand Store 创建

📅 2026/6/16 11:54:07
03-状态管理与路由——03. Zustand Store 创建
03. Zustand Store 创建一、5W1H 概述维度内容What使用 create 函数创建 Zustand storeWhy提供简单、高效的全局状态管理When需要全局状态的中大型应用Where独立的 store 文件Who需要全局状态管理的开发者Howconst useStore create((set) ({ ... }))二、What - 什么是 ZustandZustand 是一个轻量级的状态管理库名字来源于德语 “zustand”状态。它以简单、灵活、高性能著称。特点✅ 极简 API无需 Provider✅ TypeScript 友好✅ 自动优化渲染✅ 包体积小~1KB安装npminstallzustand三、Why - 为什么选择 Zustand3.1 对比其他方案特性ZustandContextReducerRedux学习成本低低高代码量少中多性能自动优化需手动优化需配置Provider不需要需要需要包大小~1KB0KB~15KB3.2 无需 Provider// Zustand 不需要 Provider 包裹 // 直接在任意组件中使用 function ComponentA() { const count useStore(state state.count); return div{count}/div; } function ComponentB() { const increment useStore(state state.increment); return button onClick{increment}/button; }四、When - 何时使用 Zustand场景推荐程度说明全局状态用户、主题✅ 强烈推荐简单高效跨组件共享数据✅ 推荐无需 Provider复杂状态逻辑✅ 推荐支持中间件简单父子通信❌ 不推荐直接用 props大型企业应用✅ 推荐性能优秀五、Where - 在哪里使用src/ ├── stores/ │ ├── userStore.js # 用户相关状态 │ ├── cartStore.js # 购物车状态 │ └── themeStore.js # 主题状态 ├── components/ │ └── Component.jsx # 直接使用 useStore └── App.jsx六、Who - 谁需要使用需要高效全局状态管理的 React 开发者。七、How - 如何创建 Store7.1 基础 Store 创建// stores/counterStore.js import { create } from zustand; const useCounterStore create((set) ({ // 状态 count: 0, // 同步操作 increment: () set((state) ({ count: state.count 1 })), decrement: () set((state) ({ count: state.count - 1 })), reset: () set({ count: 0 }), // 带参数的操作 setCount: (value) set({ count: value }) })); export default useCounterStore;7.2 使用 Store// components/Counter.jsx import useCounterStore from ../stores/counterStore; function Counter() { // 方式1获取整个 store const { count, increment, decrement, reset } useCounterStore(); // 方式2只获取需要的状态推荐 // const count useCounterStore((state) state.count); // const increment useCounterStore((state) state.increment); return ( div p计数: {count}/p button onClick{increment}/button button onClick{decrement}-/button button onClick{reset}重置/button /div ); }7.3 对象类型 Store// stores/userStore.js import { create } from zustand; const useUserStore create((set) ({ user: null, isLoading: false, error: null, setUser: (user) set({ user }), setLoading: (isLoading) set({ isLoading }), setError: (error) set({ error }), logout: () set({ user: null, isLoading: false, error: null }) })); export default useUserStore;7.4 数组类型 Store// stores/todoStore.js import { create } from zustand; const useTodoStore create((set) ({ todos: [], addTodo: (text) set((state) ({ todos: [...state.todos, { id: Date.now(), text, completed: false }] })), toggleTodo: (id) set((state) ({ todos: state.todos.map(todo todo.id id ? { ...todo, completed: !todo.completed } : todo ) })), deleteTodo: (id) set((state) ({ todos: state.todos.filter(todo todo.id ! id) })), clearTodos: () set({ todos: [] }) })); export default useTodoStore;7.5 多个 Store 示例// stores/themeStore.js const useThemeStore create((set) ({ theme: light, toggleTheme: () set((state) ({ theme: state.theme light ? dark : light })) })); // stores/cartStore.js const useCartStore create((set) ({ items: [], addItem: (item) set((state) ({ items: [...state.items, { ...item, quantity: 1 }] })), removeItem: (id) set((state) ({ items: state.items.filter(item item.id ! id) })) })); // 在组件中使用 function App() { const { theme, toggleTheme } useThemeStore(); const { items, addItem } useCartStore(); return ( div className{theme} button onClick{toggleTheme}切换主题/button {/* 其他内容 */} /div ); }7.6 使用 get 访问其他状态const useStore create((set, get) ({ count: 0, double: 0, increment: () { set((state) ({ count: state.count 1 })); // 使用 get 获取更新后的值 const newCount get().count; set({ double: newCount * 2 }); }, // 或者使用 get 计算派生值 getDouble: () { const count get().count; return count * 2; } }));7.7 带 TypeScript 的 Store// stores/userStore.tsimport{create}fromzustand;interfaceUser{id:number;name:string;email:string;}interfaceUserState{user:User|null;isLoading:boolean;error:string|null;setUser:(user:User|null)void;setLoading:(isLoading:boolean)void;setError:(error:string|null)void;fetchUser:(id:number)Promisevoid;}constuseUserStorecreateUserState((set)({user:null,isLoading:false,error:null,setUser:(user)set({user}),setLoading:(isLoading)set({isLoading}),setError:(error)set({error}),fetchUser:async(id){set({isLoading:true,error:null});try{constresponseawaitfetch(/api/users/${id});constuserawaitresponse.json();set({user,isLoading:false});}catch(error){set({error:error.message,isLoading:false});}}}));exportdefaultuseUserStore;八、最佳实践8.1 Store 拆分原则// ✅ 按功能拆分 // stores/authStore.js export const useAuthStore create(...); // stores/cartStore.js export const useCartStore create(...); // stores/themeStore.js export const useThemeStore create(...);8.2 导出选择器 Hookconst useStore create(...); // 导出自定义选择器 export const useCount () useStore(state state.count); export const useIncrement () useStore(state state.increment); // 使用 function Component() { const count useCount(); const increment useIncrement(); // ... }8.3 命名规范// ✅ 好的命名 const useUserStore create(...); const useCartStore create(...); // ❌ 不好的命名 const store create(...); const userState create(...);九、常见陷阱9.1 在组件外使用 Store// ❌ 错误在组件外直接使用 store const count useCounterStore.getState().count; // ✅ 正确在组件内使用 Hook function Component() { const count useCounterStore(state state.count); } // ✅ 或在事件处理函数中使用 getState const handleClick () { const currentCount useCounterStore.getState().count; console.log(currentCount); };9.2 忘记使用选择器// ❌ 会导致不必要的重渲染 const { count, increment } useCounterStore(); // ✅ 使用选择器优化 const count useCounterStore(state state.count); const increment useCounterStore(state state.increment);十、练习题创建一个计数器 Store1、-1、重置创建一个 Todo Store添加、删除、切换完成创建一个用户 Store登录、登出、获取用户信息十一、小结要点说明创建 Storecreate((set) ({ ... }))定义状态在返回对象中定义定义操作使用 set 函数更新状态使用 StoreuseStore(state state.value)无需 Provider直接在组件中使用