Zustand 提供了极简的持久化方案 ,核心通过内置的 persist 中间件实现,无需额外依赖(或仅需少量配置),支持 localStorage/sessionStorage/ 自定义存储(如 React Native 的 AsyncStorage)。以下是完整的持久化教程,包含基础用法、高级配置、常见问题解决。
一、基础用法(最常用)
1. 安装依赖(若需类型支持)
Zustand 核心包已内置 persist 中间件,无需额外安装,仅需确保 zustand 版本 ≥4.0.0:
bash
npm install zustand # 或 yarn add zustand
2. 基础持久化配置
tsx
import { create } from 'zustand';
import { persist } from 'zustand/middleware'; // 导入持久化中间件
// 创建带持久化的 store
const useCounterStore = create(
persist(
// 第一个参数:原始 store 逻辑
(set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 }),
}),
// 第二个参数:持久化配置
{
name: 'counter-storage', // 存储的 key(必选,用于 localStorage 标识)
// 默认存储到 localStorage,可指定为 sessionStorage:
// storage: sessionStorage,
}
)
);
// 组件中使用(和普通 zustand 用法完全一致)
function Counter() {
const { count, increment, reset } = useCounterStore();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
<button onClick={reset}>重置</button>
</div>
);
}
✅ 效果:刷新页面后,count 状态会从 localStorage 中恢复,无需额外代码。
二、高级配置(覆盖常见场景)
1. 自定义存储方式(如 React Native)
默认存储是 localStorage(Web),若需适配 React Native,可指定 AsyncStorage:
tsx
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage'; // RN 持久化存储
const useUserStore = create(
persist(
(set) => ({
userInfo: { name: '', token: '' },
setUser: (user) => set({ userInfo: user }),
}),
{
name: 'user-storage',
storage: { // 自定义存储适配器
getItem: async (name) => {
const value = await AsyncStorage.getItem(name);
return value ? JSON.parse(value) : null;
},
setItem: async (name, value) => {
await AsyncStorage.setItem(name, JSON.stringify(value));
},
removeItem: async (name) => {
await AsyncStorage.removeItem(name);
},
},
}
)
);
3. 持久化加密(敏感数据)
若存储敏感信息(如 token),可通过 serialize/deserialize 加密 / 解密:
tsx
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import CryptoJS from 'crypto-js'; // 需安装:npm install crypto-js
const SECRET_KEY = 'your-secret-key'; // 实际项目中建议从环境变量读取
const useSecureStore = create(
persist(
(set) => ({
token: '',
setToken: (token) => set({ token }),
}),
{
name: 'secure-storage',
// 序列化(存储时加密)
serialize: (state) => {
const encrypted = CryptoJS.AES.encrypt(
JSON.stringify(state),
SECRET_KEY
).toString();
return encrypted;
},
// 反序列化(读取时解密)
deserialize: (encrypted) => {
try {
const decrypted = CryptoJS.AES.decrypt(encrypted, SECRET_KEY).toString(
CryptoJS.enc.Utf8
);
return decrypted ? JSON.parse(decrypted) : {};
} catch (e) {
return {}; // 解密失败返回空状态
}
},
}
)
);
4. 手动控制持久化(清除 / 重新加载)
可通过 persist 返回的 persist 对象手动操作存储:
tsx
const useStore = create(
persist(
(set) => ({
count: 0,
increment: () => set((s) => ({ count: s.count + 1 })),
}),
{ name: 'manual-storage' }
)
);
// 获取持久化操作方法
const { persist } = useStore;
// 手动清除持久化数据
function clearStorage() {
persist.clearStorage(); // 清除 localStorage 中的数据
}
// 手动重新加载持久化数据
function reloadStorage() {
persist.rehydrate(); // 从存储中重新加载状态到 store
}
// 组件中使用
function ControlPanel() {
return (
<div>
<button onClick={clearStorage}>清除持久化数据</button>
<button onClick={reloadStorage}>重新加载数据</button>
</div>
);
}
5. 持久化冲突处理(多标签页同步)
默认情况下,多标签页修改状态可能导致冲突,可通过 merge 配置合并状态:
tsx
const useStore = create(
persist(
(set) => ({
count: 0,
}),
{
name: 'sync-storage',
// 合并多标签页的状态(取最新的 count)
merge: (persistedState, currentState) => {
return {
...currentState,
count: persistedState.count > currentState.count ? persistedState.count : currentState.count,
};
},
}
)
);
三、常见问题解决
1. 状态不持久化?
- 检查
name配置是否唯一(避免和其他存储冲突); - 确认存储的状态是可序列化的(不能存函数、Symbol 等,
persist会自动忽略不可序列化字段); - 若用自定义存储(如 RN AsyncStorage),检查是否安装并链接依赖。
2. 持久化后状态更新不生效?
- 确保修改状态时使用
set方法(而非直接赋值); - 若手动修改了 localStorage,需调用
persist.rehydrate()重新加载。
3. 类型报错(TypeScript)?
为 persist 显式指定状态类型
tsx
interface CounterState {
count: number;
increment: () => void;
}
const useCounterStore = create<CounterState>()(
persist(
(set) => ({
count: 0,
increment: () => set((s) => ({ count: s.count + 1 })),
}),
{ name: 'counter-storage' }
)
);
四、总结
Zustand 持久化的核心优势:
- 极简配置:一行代码实现基础持久化,无需繁琐的 reducer/action 配置;
- 高度灵活:支持自定义存储、加密、部分持久化、手动控制;
- 跨平台:适配 Web(localStorage/sessionStorage)、React Native(AsyncStorage);
- 性能友好:仅在状态变更时触发存储,无多余性能开销。
实际开发中,优先使用基础配置,敏感数据加解密,多场景适配自定义存储即可满足 99% 的需求。