Table of Contents
Zustand 是一个轻量级、快速且可扩展的 React 状态管理库。它以其简洁的 API 和基于 Hook 的设计理念受到广泛欢迎。本文将结合实际项目代码,总结 Zustand 的基础用法以及 Immer、Persist 等高级中间件的实战应用。
1. 基础篇:快速上手
1.1 创建 Store
最基础的 Zustand 用法是通过 create 方法创建一个 Hook。Store 中包含了状态(State)和更新状态的方法(Actions)。
参考项目中的 app/store/price.ts:
import { create } from 'zustand'
interface PriceStore { price: number state: number increment: () => void decrement: () => void resetPrice: () => void getPrice: () => number setPrice: (price: number) => void}
const usePriceStore = create<PriceStore>((set, get) => ({ price: 0, state: 123, increment: () => set((state) => ({ price: state.price + 1 })), decrement: () => set((state) => ({ price: state.price - 1 })), resetPrice: () => set(() => ({ price: 0 })), getPrice: () => get().price, setPrice: (price: number) => set(() => ({ price: price })),}))
export default usePriceStore1.2 在组件中使用
创建好 Store 后,可以直接在组件中调用这个 Hook 来获取状态和方法。
参考 app/pages/Zustand/index.tsx:
import usePriceStore from '~/store/price'
export default function Zustand() { const priceStore = usePriceStore() return ( <div className="w-120 h-120 bg-[#242424] box-border"> <div className='text-white text-4xl bg-amber-300 w-30 h-40 mt-4 relative box-border'>{priceStore.price}</div> <div className="h-40 w-full flex items-center justify-start p-4 gap-4"> <div className="bg-blue-300 text-white w-40 h-40 flex items-center justify-center cursor-pointer" onClick={() => priceStore.increment()} > + </div> <div className="bg-red-300 text-white w-40 h-40 flex items-center justify-center cursor-pointer" onClick={() => priceStore.decrement()} > — </div> <div className="bg-green-300 text-white w-40 h-40 flex items-center justify-center cursor-pointer" onClick={() => priceStore.resetPrice()} > 重置 </div> </div> </div> )}2. 进阶篇:中间件与复杂状态
对于更复杂的场景,Zustand 提供了丰富的中间件支持。在 app/store/hlw.ts 中,我们结合了 immer、persist 和 subscribeWithSelector。
2.1 组合使用中间件
在 app/store/hlw.ts 中,展示了如何使用 createStore(Vanilla Store)并组合多个中间件:
import { createStore } from 'zustand/vanilla'import { immer } from 'zustand/middleware/immer'import { persist, createJSONStorage } from 'zustand/middleware'import { subscribeWithSelector } from 'zustand/middleware'
export interface HLW { name: '大娃' | '二娃' | '三娃' | '四娃' | '五娃' | '六娃' | '七娃' | undefined level: '初始' | '超进化'}
const data = [ { name: '大娃', level: '初始' }, { name: '二娃', level: '初始' }, { name: '三娃', level: '初始' }, { name: '四娃', level: '初始' }, { name: '五娃', level: '初始' }, { name: '六娃', level: '初始' }, { name: '七娃', level: '初始' },]
const kunkun = { name: '房房', age: 18, gender: '男', hobbies: { sing: '唱歌', dance: '跳舞', rap: 'rap', basketball: '篮球', },}
interface HLWStore { hlws: HLW[] kunkun: typeof kunkun updateName: (name: string) => void updateRap: (rap: string) => void updateBasketball: (basketball: string) => void upgrade: (name: HLW['name']) => void setAge: () => void reset: () => void}
const useHLWStore = createStore<HLWStore>()( immer( subscribeWithSelector( persist( (set) => ({ hlws: data as HLW[], kunkun, updateName: (name: string) => { set((state) => { state.kunkun.name = name }) }, updateRap: (rap: string) => { set((state) => { state.kunkun.hobbies.rap = rap }) }, updateBasketball: (basketball: string) => { set((state) => { state.kunkun.hobbies.basketball = basketball }) }, upgrade: (name: HLW['name']) => set((state) => { let hlw = state.hlws.find((hlw) => hlw.name === name) hlw && (hlw.level = '超进化') }), reset: () => set((state) => { state.hlws = data as HLW[] state.kunkun = kunkun }), setAge: () => { set((state) => { state.kunkun.age++ }) }, }), { name: 'hlw', storage: createJSONStorage(() => localStorage), } ) ) ))
export default useHLWStore在这个例子中:
immer让我们能够直接修改嵌套状态(如state.kunkun.hobbies.rap = rap)。persist将状态持久化到localStorage中,key 为hlw。subscribeWithSelector允许我们精确订阅 store 的一部分。- 使用
createStore创建的是一个 Vanilla Store,在 React 组件中使用时需要配合useStorehook。
2.2 订阅状态变化与 useShallow 优化
在组件 app/pages/HLW/B.tsx 中,我们展示了如何使用 useStore 结合 useShallow 进行性能优化,以及如何使用 subscribe 监听状态变化。
import { useEffect, useState } from 'react'import { useStore } from 'zustand'import { useShallow } from 'zustand/react/shallow'import useHLWStore from '~/store/hlw'
export default function B() { // 使用 useShallow 进行浅比较,避免不必要的重渲染 const { rap, basketball, age } = useStore( useHLWStore, useShallow((state) => ({ rap: state.kunkun.hobbies.rap, age: state.kunkun.age, basketball: state.kunkun.hobbies.basketball, })) )
const [status, setStatus] = useState<'单身' | '结婚'>('单身')
// 使用 subscribe 监听 age 的变化 useEffect(() => { useHLWStore.subscribe( (state) => state.kunkun.age, (age) => { console.log('执行了useEffect') if (age >= 26) { setStatus('结婚') } else { setStatus('单身') } } ) }, [])
return ( <div className="w-100 h-50 border border-amber-700 rounded-sm p-4"> <div> 爱好: <span> {rap}-{basketball} </span> </div> <div> 年龄:<span>{age}</span> </div> <div> 状态:<span>{status}</span> </div> </div> )}2.3 操作复杂状态
组件 app/pages/HLW/A.tsx 展示了如何调用 store 中的 action 来修改复杂状态:
import { Button, Input, Select } from 'antd'import { useState } from 'react'import useHLWStore, { type HLW } from '~/store/hlw'import { useStore } from 'zustand'
export default function A() { const hlwStore = useStore(useHLWStore) const [name, setName] = useState<HLW['name'] | undefined>()
function superAd() { hlwStore.upgrade(name) } function reset() { hlwStore.reset() } function updateName() { hlwStore.updateName('房房222') } function updateRap() { hlwStore.updateRap('rap222') } function updateBasketball() { hlwStore.updateBasketball('篮球222') } function setAge() { hlwStore.setAge() }
return ( <div className="w-100 h-50 border border-amber-700 rounded-sm p-4"> <Button className='mr-2' onClick={superAd}>超进化</Button> <Button className='mr-2' onClick={reset}>重置</Button> <Select className="w-30" options={hlwStore.hlws.map((hlw) => ({ label: hlw.name, value: hlw.name }))} onChange={(value) => { setName(value) }} /> <Button className='mr-2' onClick={()=>updateName()}>修改姓名</Button> <Button className='mr-2' onClick={()=>updateRap()}>修改rap</Button> <Button className='mr-2' onClick={()=>updateBasketball()}>修改篮球</Button> <Button className='mr-2' onClick={()=>setAge()}>增加年龄</Button> </div> )}总结
Zustand 提供了极其灵活的状态管理方案。
- 简单场景:直接使用
create和基础 Actions。 - 复杂场景:组合使用
immer处理深层更新,persist处理持久化。 - 性能敏感:利用 Selector 和
useShallow精确控制渲染。 - 逻辑解耦:利用
subscribe在组件外监听状态变化。
通过合理组合这些特性,我们可以构建出既高效又易于维护的 React 应用状态管理层。
评论 (0)
请先登录后再发表评论