Zustand状态库(简洁、强大、易用的React状态管理工具)
1、Zustand状态管理认识
Zustand 是一个轻量级的状态管理库,非常适合用于管理全局状态,包括用户认证信息在React项目之中,接下来我们就在项目中进行使用。
🍎官网
JS
Zustand官网
https://zustand.docs.pmnd.rs/getting-started/introduction
Zustand中文官网
https://awesomedevin.github.io/zustand-vue/docs/introduce/start/zustand
🍎选择它的原因
小型项目我们使用了Zustand,而不是庞大的Redux
React项目中,组件状态管理通常如下
- 组件内状态:小型项目中使用useState足矣
- Context传递:中型项目通过Context共享状态
- 全局状态管理:大型项目需要集中式状态管理
2、安装使用
javascript
yarn add zustand
安装以后查看一下自己的版本
我本地版本
"zustand": "^5.0.8"
🍎Zustand非持久化使用
接下来我们一步一步使用 Zustand 来保存登录的 token 信息,并实现登录和退出功能。
javascript
src\store\userStore.ts
// src/store/authStore.ts
import { create } from 'zustand';
interface AuthState {
token: string | null;
user: any | null;
isAuthenticated: boolean;
login: (token: string, user?: any) => void;
logout: () => void;
loading: boolean;
setLoading: (loading: boolean) => void;
}
// 直接创建 store
export const useAuthStore = create<AuthState>((set) => ({
token: null,
user: null,
isAuthenticated: false,
loading: true,
// 登录函数
login: (token, user) => {
set({ token, user, isAuthenticated: true });
},
// 退出函数
logout: () => {
set({ token: null, user: null, isAuthenticated: false });
},
// 设置加载状态
setLoading: (loading) => {
set({ loading });
},
}));
🍎测试一下我们的登录状态
javascript
// src/components/AuthStatus.tsx
import React from 'react';
import { useAuthStore } from '@/store/authStore';
export const AuthStatus=() => {
const { token, user, isAuthenticated, loading, login, logout } = useAuthStore();
const handleLogin = () => {
// 模拟登录
login('fake-jwt-token', { id: 1, name: 'John Doe', email: 'john@example.com' });
};
const handleLogout = () => {
// 模拟退出
logout();
};
return (
<div>
<h2>认证状态</h2>
<p>是否已认证: {isAuthenticated ? '是' : '否'}</p>
<p>Token: {token || '无'}</p>
{user && (
<div>
<p>用户ID: {user.id}</p>
<p>用户名: {user.name}</p>
<p>邮箱: {user.email}</p>
</div>
)}
<div style={{ marginTop: '16px' }}>
{!isAuthenticated ? (
<button onClick={handleLogin}>模拟登录</button>
) : (
<button onClick={handleLogout}>退出登录</button>
)}
</div>
</div>
);
};
export default AuthStatus;
这时候我们还没写localStorage存储,那么会导致什么问题呢
刷新页面以后
store 中的状态将不会自动保存到 localStorage 中,页面刷新后状态会重置为初始值。
🍎手动处理 token
接下来我们手动处理 token 的持久化(例如,只持久化 token 而不持久化其他状态)
你可以在登录和退出函数中手动处理 localStorage 的读写
javascript
// src/store/authStore.ts
import { create } from 'zustand';
interface AuthState {
token: string | null;
user: any | null;
isAuthenticated: boolean;
login: (token: string, user?: any) => void;
logout: () => void;
loading: boolean;
setLoading: (loading: boolean) => void;
}
export const useAuthStore = create<AuthState>((set) => ({
token: localStorage.getItem('token'), // 初始化时从 localStorage 读取
user: null,
isAuthenticated: !!localStorage.getItem('token'), // 根据 token 是否存在设置认证状态
loading: true,
// 登录函数
login: (token, user) => {
// 将 token 保存到 localStorage
localStorage.setItem('token', token);
set({ token, user, isAuthenticated: true });
},
// 退出函数
logout: () => {
// 从 localStorage 移除 token
localStorage.removeItem('token');
set({ token: null, user: null, isAuthenticated: false });
},
// 设置加载状态
setLoading: (loading) => {
set({ loading });
},
}));
🍎持久化的中间件 persist
中间件
这个时候我们刷新会发现只持久化 token,而其他状态(如 user 和 loading)不会持久化,页面刷新后会重置为初始值
这个时候就需要用到zustand持久化的中间件persist
以及createJSONStorage
javascript
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const useStore = create(
persist(
(set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}),
{
name: 'count-storage', // localStorage 中的键名
}
)
);
略微完善一下以后
javascript
// src/store/authStore.ts
import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
interface User {
id: number;
name: string;
email: string;
// 可以添加更多用户属性
}
interface AuthState {
token: string | null;
user: User | null;
isAuthenticated: boolean;
login: (token: string, user: User) => void;
logout: () => void;
updateUserData: (userData: Partial<User>) => void;
clearAuth: () => void;
}
// 创建 authStore
export const useAuthStore = create<AuthState>()(
persist(
(set) => ({
// 初始状态
token: null,
user: null,
isAuthenticated: false,
// 登录函数
login: (token, user) => {
set({
token,
user,
isAuthenticated: true,
});
},
// 退出登录函数
logout: () => {
set({
token: null,
user: null,
isAuthenticated: false,
});
},
// 更新用户数据函数
updateUserData: (userData) => {
set((state) => ({
user: state.user ? { ...state.user, ...userData } : null,
}));
},
// 清除认证状态函数
clearAuth: () => {
set({
token: null,
user: null,
isAuthenticated: false,
});
},
}),
{
name: 'AdminToken', // localStorage 中的键名
storage: createJSONStorage(() => localStorage),
partialize: (state) => ({
token: state.token,
user: state.user,
isAuthenticated: state.isAuthenticated,
}),
// 可选:自定义版本控制,当 store 结构发生变化时使用
version: 1,
}
)
);
再次测试,即便我们刷新,存储在本地的数据也不会丢失
3、项目使用
接下来在我们的项目之中进行使用
使用起来也非常的简单,可以拆分API的方式,也可以API直接组合的方式进行使用
javascript
import { useAuthStore } from '@/store/authStore';
const { login} = useAuthStore();
login(res.token, res.user);
不得不说,太简单便捷了