欢迎光临
我们一直在努力

03-状态管理与路由——07. Zustand 中间件与最佳实践

07. Zustand 中间件与最佳实践

一、5W1H 概述

维度内容
What 使用 persist、devtools 等中间件扩展 Zustand
Why 实现状态持久化、调试支持
When 需要本地存储、Redux DevTools 调试时
Where store 创建时包裹中间件
Who 需要高级功能的开发者
How create(persist(…, { name: 'storage' }))

二、What – 什么是中间件?

中间件是 Zustand 提供的扩展功能,可以增强 store 的能力。

常用中间件

中间件用途
persist 状态持久化到 localStorage/sessionStorage
devtools Redux DevTools 调试支持
immer 简化不可变更新
subscribeWithSelector 支持选择器订阅
combine 合并多个 store

三、Why – 为什么需要中间件?

3.1 持久化

刷新页面后保持状态(用户登录、主题设置等)。

3.2 调试

使用 Redux DevTools 查看状态变化、时间旅行调试。

3.3 简化代码

Immer 中间件简化嵌套状态更新。


四、When – 何时使用?

场景推荐中间件
需要本地存储 persist
需要调试 devtools
复杂嵌套更新 immer
生产环境 组合使用

五、Where – 在哪里使用?

import { create } from 'zustand';
import { persist, devtools } from 'zustand/middleware';

const useStore = create(
devtools(
persist(
(set) => ({
// store 定义
}),
{ name: 'storage-key' }
)
)
);


六、Who – 谁需要使用?

需要持久化存储或调试支持的开发者。


七、How – 如何使用中间件?

7.1 persist 中间件

import { create } from 'zustand';
import { persist } from 'zustand/middleware';

const useStore = create(
persist(
(set) => ({
count: 0,
user: null,
theme: 'light',

increment: () => set((state) => ({ count: state.count + 1 })),
setUser: (user) => set({ user }),
setTheme: (theme) => set({ theme })
}),
{
name: 'app-storage', // localStorage key
getStorage: () => localStorage, // 默认 localStorage
}
)
);

7.2 部分持久化

const useStore = create(
persist(
(set) => ({
count: 0,
temp: '不持久化',
user: null,

increment: () => set((state) => ({ count: state.count + 1 })),
setTemp: (temp) => set({ temp })
}),
{
name: 'app-storage',
// 只持久化 count 和 user
partialize: (state) => ({ count: state.count, user: state.user })
}
)
);

7.3 使用 sessionStorage

const useStore = create(
persist(
(set) => ({
sessionData: null,
setSessionData: (data) => set({ sessionData: data })
}),
{
name: 'session-storage',
getStorage: () => sessionStorage,
}
)
);

7.4 自定义存储

const useStore = create(
persist(
(set) => ({ … }),
{
name: 'custom-storage',
getStorage: () => ({
getItem: (key) => {
const value = localStorage.getItem(key);
console.log('读取:', key, value);
return value;
},
setItem: (key, value) => {
console.log('保存:', key, value);
localStorage.setItem(key, value);
},
removeItem: (key) => {
console.log('删除:', key);
localStorage.removeItem(key);
},
}),
}
)
);

7.5 版本控制

const useStore = create(
persist(
(set) => ({
version: 2,
data: { oldField: 'value', newField: '' }
}),
{
name: 'app-storage',
version: 2,
migrate: (persistedState, version) => {
if (version === 1) {
// 迁移逻辑
return {
…persistedState,
newField: persistedState.oldField || ''
};
}
return persistedState;
},
}
)
);

7.6 devtools 中间件

import { devtools } from 'zustand/middleware';

const useStore = create(
devtools(
(set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 }), false, 'increment'),
decrement: () => set((state) => ({ count: state.count – 1 }), false, 'decrement'),
reset: () => set({ count: 0 }, false, 'reset')
}),
{ name: 'CounterStore' }
)
);

7.7 immer 中间件

npm install immer

import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';

const useStore = create(
immer((set) => ({
user: {
profile: { name: '张三', age: 25 },
settings: { theme: 'light', notifications: true }
},
todos: [],

// 直接修改,immer 处理不可变性
updateProfileName: (name) =>
set((state) => {
state.user.profile.name = name;
}),

updateSettings: (settings) =>
set((state) => {
Object.assign(state.user.settings, settings);
}),

addTodo: (text) =>
set((state) => {
state.todos.push({ id: Date.now(), text, completed: false });
}),

toggleTodo: (id) =>
set((state) => {
const todo = state.todos.find(t => t.id === id);
if (todo) todo.completed = !todo.completed;
})
}))
);

7.8 组合多个中间件

import { create } from 'zustand';
import { persist, devtools, immer } from 'zustand/middleware';

const useStore = create(
devtools(
persist(
immer((set) => ({
user: null,
token: null,
theme: 'light',

login: async (email, password) =>
set((state) => {
// 使用 immer 直接修改
state.loading = true;
}),

setTheme: (theme) =>
set((state) => {
state.theme = theme;
}),

logout: () =>
set((state) => {
state.user = null;
state.token = null;
})
})),
{ name: 'auth-storage' }
),
{ name: 'AuthStore' }
)
);


八、最佳实践

8.1 Store 拆分

// stores/userStore.js
export const useUserStore = create((set) => ({
user: null,
setUser: (user) => set({ user })
}));

// stores/cartStore.js
export const useCartStore = create((set) => ({
items: [],
addItem: (item) => set((state) => ({ items: […state.items, item] }))
}));

// stores/themeStore.js
export const useThemeStore = create(
persist(
(set) => ({
theme: 'light',
toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' }))
}),
{ name: 'theme-storage' }
)
);

8.2 导出选择器 Hook

const useStore = create(…);

// 导出自定义选择器
export const useCount = () => useStore(state => state.count);
export const useIncrement = () => useStore(state => state.increment);
export const useDecrement = () => useStore(state => state.decrement);

// 使用
function Component() {
const count = useCount();
const increment = useIncrement();
// …
}

8.3 重置 Store

const initialState = { count: 0, user: null, todos: [] };

const useStore = create((set) => ({
…initialState,
reset: () => set(initialState),
increment: () => set((state) => ({ count: state.count + 1 })),
setUser: (user) => set({ user }),
addTodo: (text) => set((state) => ({
todos: […state.todos, { id: Date.now(), text }]
}))
}));

8.4 类型安全(TypeScript)

interface User {
id: number;
name: string;
}

interface UserState {
user: User | null;
setUser: (user: User | null) => void;
}

const useUserStore = create<UserState>()(
persist(
(set) => ({
user: null,
setUser: (user) => set({ user })
}),
{ name: 'user-storage' }
)
);

8.5 条件持久化

const useStore = create(
persist(
(set) => ({
user: null,
rememberMe: false
}),
{
name: 'auth-storage',
// 只有勾选"记住我"时才持久化
partialize: (state) => state.rememberMe ? { user: state.user } : {}
}
)
);


九、练习题

  • 创建一个带持久化的主题 Store
  • 创建一个带 DevTools 的计数器 Store
  • 创建一个使用 immer 简化更新的 Todo Store

  • 十、小结

    中间件用途配置
    persist 持久化存储 { name: 'key' }
    devtools 调试支持 { name: 'StoreName' }
    immer 简化更新 直接修改状态
    组合使用 多中间件叠加 嵌套包裹

    赞(0)
    未经允许不得转载:171主机测评 » 03-状态管理与路由——07. Zustand 中间件与最佳实践
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址