【React】状态管理之Zustand
🌈个人主页: 鑫宝Code
🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础
💫个人格言: "如无必要,勿增实体"
文章目录
- 状态管理之Zustand
- 引言
- 1. Zustand 的核心特点
- 1.1 简单直观的 API
- 1.2 无需 Provider
- 2. 高级特性与用法
- 2.1 异步操作处理
- 2.2 中间件支持
- 2.3 状态切片(Slices)
- 3. 性能优化
- 3.1 选择性订阅
- 3.2 浅比较
- 4. 实际应用场景
- 4.1 表单状态管理
- 4.2 认证状态管理
- 5. 最佳实践
- 5.1 Store 组织
- 5.2 TypeScript 集成
- 总结
状态管理之Zustand
引言
Zustand 是一个轻量级的状态管理库,以其简单、灵活和高性能的特点在 React 社区中快速崛起。本文将深入探讨 Zustand 的核心概念、使用方法和最佳实践。
1. Zustand 的核心特点
1.1 简单直观的 API
Zustand 采用极简的 API 设计,创建 store 非常简单:
import create from 'zustand'
interface BearStore {
bears: number
increase: () => void
decrease: () => void
}
const useStore = create<BearStore>((set) => ({
bears: 0,
increase: () => set((state) => ({ bears: state.bears + 1 })),
decrease: () => set((state) => ({ bears: state.bears - 1 }))
}))
1.2 无需 Provider
与 Redux 和 Context API 不同,Zustand 不需要 Provider 包裹:
function BearCounter() {
const bears = useStore((state) => state.bears)
return <h1>{bears} around here...</h1>
}
function Controls() {
const increase = useStore((state) => state.increase)
const decrease = useStore((state) => state.decrease)
return (
<div>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
)
}
2. 高级特性与用法
2.1 异步操作处理
interface TodoStore {
todos: Todo[]
loading: boolean
fetchTodos: () => Promise<void>
}
const useTodoStore = create<TodoStore>((set) => ({
todos: [],
loading: false,
fetchTodos: async () => {
set({ loading: true })
try {
const response = await fetch('https://api.example.com/todos')
const todos = await response.json()
set({ todos, loading: false })
} catch (error) {
set({ loading: false })
console.error(error)
}
}
}))
2.2 中间件支持
Zustand 提供了强大的中间件支持:
import { persist, devtools } from 'zustand/middleware'
const useStore = create(
devtools(
persist(
(set) => ({
bears: 0,
increase: () => set((state) => ({ bears: state.bears + 1 }))
}),
{ name: 'bear-storage' }
)
)
)
2.3 状态切片(Slices)
组织大型应用状态:
interface AuthSlice {
user: User | null
login: (credentials: Credentials) => Promise<void>
logout: () => void
}
interface TodoSlice {
todos: Todo[]
addTodo: (todo: Todo) => void
}
const createAuthSlice = (set) => ({
user: null,
login: async (credentials) => {
const user = await loginApi(credentials)
set({ user })
},
logout: () => set({ user: null })
})
const createTodoSlice = (set) => ({
todos: [],
addTodo: (todo) => set((state) => ({
todos: [...state.todos, todo]
}))
})
const useStore = create((set) => ({
...createAuthSlice(set),
...createTodoSlice(set)
}))
3. 性能优化
3.1 选择性订阅
Zustand 支持细粒度的状态订阅:
function TodoCount() {
// 只在 todos.length 变化时重渲染
const todoCount = useStore((state) => state.todos.length)
return <div>Todo Count: {todoCount}</div>
}
3.2 浅比较
使用 shallow 进行浅比较:
import shallow from 'zustand/shallow'
function TodoList() {
const { todos, addTodo } = useStore(
(state) => ({
todos: state.todos,
addTodo: state.addTodo
}),
shallow
)
return (
// 组件实现
)
}
4. 实际应用场景
4.1 表单状态管理
interface FormStore {
formData: {
name: string
email: string
}
setField: (field: string, value: string) => void
resetForm: () => void
}
const useFormStore = create<FormStore>((set) => ({
formData: {
name: '',
email: ''
},
setField: (field, value) =>
set((state) => ({
formData: {
...state.formData,
[field]: value
}
})),
resetForm: () =>
set({
formData: {
name: '',
email: ''
}
})
}))
4.2 认证状态管理
interface AuthStore {
token: string | null
user: User | null
login: (credentials: Credentials) => Promise<void>
logout: () => void
updateUser: (user: Partial<User>) => void
}
const useAuthStore = create<AuthStore>()(
persist(
(set) => ({
token: null,
user: null,
login: async (credentials) => {
const { token, user } = await loginApi(credentials)
set({ token, user })
},
logout: () => set({ token: null, user: null }),
updateUser: (userData) =>
set((state) => ({
user: state.user ? { ...state.user, ...userData } : null
}))
}),
{
name: 'auth-storage',
getStorage: () => localStorage
}
)
)
5. 最佳实践
5.1 Store 组织
// stores/index.ts
import { useAuthStore } from './authStore'
import { useTodoStore } from './todoStore'
import { useUIStore } from './uiStore'
export {
useAuthStore,
useTodoStore,
useUIStore
}
5.2 TypeScript 集成
// types.ts
interface Todo {
id: string
title: string
completed: boolean
}
interface TodoState {
todos: Todo[]
loading: boolean
error: string | null
addTodo: (title: string) => void
toggleTodo: (id: string) => void
removeTodo: (id: string) => void
}
// todoStore.ts
const useTodoStore = create<TodoState>((set) => ({
todos: [],
loading: false,
error: null,
addTodo: (title) =>
set((state) => ({
todos: [
...state.todos,
{
id: Date.now().toString(),
title,
completed: false
}
]
})),
toggleTodo: (id) =>
set((state) => ({
todos: state.todos.map((todo) =>
todo.id === id
? { ...todo, completed: !todo.completed }
: todo
)
})),
removeTodo: (id) =>
set((state) => ({
todos: state.todos.filter((todo) => todo.id !== id)
}))
}))
总结
Zustand 的优势在于:
- 简单直观的 API 设计
- 无需 Provider 的使用方式
- 出色的 TypeScript 支持
- 强大的中间件系统
- 优秀的性能表现
使用 Zustand 可以帮助我们:
- 降低状态管理的复杂度
- 提高应用的可维护性
- 优化应用性能
- 提供更好的开发体验
在选择状态管理方案时,如果你需要一个轻量级但功能强大的解决方案,Zustand 是一个值得考虑的选择。它特别适合中小型应用,但通过良好的状态组织,同样可以胜任大型应用的状态管理需求。