创建 Store #
基本创建 #
Zustand 使用 create 函数创建 store。这是 Zustand 的核心 API,也是你唯一需要记住的函数。
最简单的 Store #
tsx
import { create } from 'zustand'
const useStore = create((set) => ({
count: 0,
}))
完整的 Store 结构 #
tsx
import { create } from 'zustand'
interface StoreState {
// 状态
count: number
name: string
// 更新函数
increment: () => void
decrement: () => void
setName: (name: string) => void
reset: () => void
}
const useStore = create<StoreState>((set) => ({
// 初始状态
count: 0,
name: '',
// 更新函数
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
setName: (name) => set({ name }),
reset: () => set({ count: 0, name: '' }),
}))
理解 set 函数 #
set 函数是更新状态的唯一方式。它支持两种调用模式。
直接设置 #
tsx
const useStore = create((set) => ({
count: 0,
// 直接设置新值
setCount: (value) => set({ count: value }),
// 设置多个状态
setMultiple: () => set({ count: 10, name: 'John' }),
}))
基于前一个状态 #
tsx
const useStore = create((set) => ({
count: 0,
// 基于前一个状态更新
increment: () => set((state) => ({ count: state.count + 1 })),
// 复杂计算
doubleAndAdd: (value) => set((state) => ({
count: state.count * 2 + value
})),
}))
set 函数的第三个参数 #
set 函数接受第三个参数,用于标识更新来源(调试用):
tsx
const useStore = create((set) => ({
count: 0,
increment: () => set(
(state) => ({ count: state.count + 1 }),
false, // 是否替换整个状态
'increment' // action 名称(用于 devtools)
),
}))
理解 get 函数 #
get 函数用于获取当前状态,常用于读取状态进行计算:
tsx
const useStore = create((set, get) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
// 使用 get 获取当前状态
logCurrentCount: () => {
console.log('Current count:', get().count)
},
// 在异步操作中使用
asyncIncrement: async () => {
const currentCount = get().count
await someAsyncOperation()
set({ count: currentCount + 1 })
},
}))
状态类型定义 #
基本类型 #
tsx
interface State {
count: number
name: string
isActive: boolean
tags: string[]
}
const useStore = create<State>((set) => ({
count: 0,
name: '',
isActive: false,
tags: [],
}))
对象类型 #
tsx
interface User {
id: string
name: string
email: string
}
interface State {
user: User | null
settings: {
theme: 'light' | 'dark'
language: string
}
}
const useStore = create<State>((set) => ({
user: null,
settings: {
theme: 'light',
language: 'zh-CN',
},
updateUser: (user: User) => set({ user }),
updateTheme: (theme: 'light' | 'dark') =>
set((state) => ({
settings: { ...state.settings, theme }
})),
}))
复杂嵌套类型 #
tsx
interface Todo {
id: string
text: string
completed: boolean
}
interface TodoState {
todos: Todo[]
filter: 'all' | 'active' | 'completed'
addTodo: (text: string) => void
toggleTodo: (id: string) => void
removeTodo: (id: string) => void
setFilter: (filter: TodoState['filter']) => void
}
const useTodoStore = create<TodoState>((set) => ({
todos: [],
filter: 'all',
addTodo: (text) => set((state) => ({
todos: [
...state.todos,
{ id: Date.now().toString(), text, 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)
})),
setFilter: (filter) => set({ filter }),
}))
创建模式 #
模式一:内联定义 #
最简单直接的方式:
tsx
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}))
模式二:分离定义 #
将状态和逻辑分离:
tsx
interface State {
count: number
increment: () => void
}
const initialState = {
count: 0,
}
const storeActions = (set: any, get: any) => ({
increment: () => set((state: State) => ({ count: state.count + 1 })),
getCount: () => get().count,
})
const useStore = create<State>((set, get) => ({
...initialState,
...storeActions(set, get),
}))
模式三:类风格 #
使用类来组织 store:
tsx
interface State {
count: number
increment: () => void
decrement: () => void
}
class CounterStore {
private set: any
private get: any
constructor(set: any, get: any) {
this.set = set
this.get = get
}
get initialState() {
return { count: 0 }
}
get actions() {
return {
increment: this.increment,
decrement: this.decrement,
}
}
private increment = () => {
this.set((state: State) => ({ count: state.count + 1 }))
}
private decrement = () => {
this.set((state: State) => ({ count: state.count - 1 }))
}
}
const useStore = create<State>((set, get) => {
const store = new CounterStore(set, get)
return {
...store.initialState,
...store.actions,
}
})
实际案例 #
用户认证 Store #
tsx
interface User {
id: string
name: string
email: string
role: 'admin' | 'user'
}
interface AuthState {
user: User | null
token: string | null
isAuthenticated: boolean
isLoading: boolean
error: string | null
login: (email: string, password: string) => Promise<void>
logout: () => void
clearError: () => void
}
const useAuthStore = create<AuthState>((set, get) => ({
user: null,
token: null,
isAuthenticated: false,
isLoading: false,
error: null,
login: async (email, password) => {
set({ isLoading: true, error: null })
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
})
if (!response.ok) {
throw new Error('登录失败')
}
const data = await response.json()
set({
user: data.user,
token: data.token,
isAuthenticated: true,
isLoading: false,
})
} catch (error) {
set({
error: error instanceof Error ? error.message : '登录失败',
isLoading: false,
})
}
},
logout: () => {
set({
user: null,
token: null,
isAuthenticated: false,
error: null,
})
},
clearError: () => set({ error: null }),
}))
购物车 Store #
tsx
interface CartItem {
id: string
productId: string
name: string
price: number
quantity: number
}
interface CartState {
items: CartItem[]
totalItems: number
totalPrice: number
addItem: (item: Omit<CartItem, 'id'>) => void
removeItem: (id: string) => void
updateQuantity: (id: string, quantity: number) => void
clearCart: () => void
}
const useCartStore = create<CartState>((set, get) => ({
items: [],
totalItems: 0,
totalPrice: 0,
addItem: (item) => set((state) => {
const existingItem = state.items.find(i => i.productId === item.productId)
let newItems: CartItem[]
if (existingItem) {
newItems = state.items.map(i =>
i.productId === item.productId
? { ...i, quantity: i.quantity + item.quantity }
: i
)
} else {
newItems = [...state.items, { ...item, id: Date.now().toString() }]
}
return {
items: newItems,
totalItems: newItems.reduce((sum, i) => sum + i.quantity, 0),
totalPrice: newItems.reduce((sum, i) => sum + i.price * i.quantity, 0),
}
}),
removeItem: (id) => set((state) => {
const newItems = state.items.filter(i => i.id !== id)
return {
items: newItems,
totalItems: newItems.reduce((sum, i) => sum + i.quantity, 0),
totalPrice: newItems.reduce((sum, i) => sum + i.price * i.quantity, 0),
}
}),
updateQuantity: (id, quantity) => set((state) => {
if (quantity <= 0) {
return get().removeItem(id)
}
const newItems = state.items.map(i =>
i.id === id ? { ...i, quantity } : i
)
return {
items: newItems,
totalItems: newItems.reduce((sum, i) => sum + i.quantity, 0),
totalPrice: newItems.reduce((sum, i) => sum + i.price * i.quantity, 0),
}
}),
clearCart: () => set({
items: [],
totalItems: 0,
totalPrice: 0,
}),
}))
最佳实践 #
1. 保持 Store 单一职责 #
tsx
// ✅ 好的做法:每个 store 负责一个领域
const useUserStore = create((set) => ({ /* 用户相关 */ }))
const useCartStore = create((set) => ({ /* 购物车相关 */ }))
const useThemeStore = create((set) => ({ /* 主题相关 */ }))
// ❌ 不推荐:一个 store 管理所有状态
const useAppStore = create((set) => ({
user: {},
cart: {},
theme: {},
// ...太多职责
}))
2. 使用 TypeScript 类型 #
tsx
// ✅ 始终定义类型
interface State {
count: number
increment: () => void
}
const useStore = create<State>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}))
3. 命名规范 #
tsx
// ✅ 好的命名
const useUserStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
clearUser: () => set({ user: null }),
}))
// ❌ 不好的命名
const useStore = create((set) => ({
data: null,
update: (d) => set({ data: d }),
}))
总结 #
创建 Store 是使用 Zustand 的第一步,关键点:
- 使用
create函数创建 store - 使用
set函数更新状态 - 使用
get函数读取当前状态 - 定义清晰的 TypeScript 类型
- 保持 store 的单一职责
接下来,让我们学习 使用 Store,掌握在组件中使用 store 的各种技巧。
最后更新:2026-03-28