Kailiming Blog

React状态管理:Zustand

前端
React
TypeScripe

小型、快速且可扩展的 bearbones 状态管理解决方案。

React状态管理:Zustand

基本使用

通过create方法创建一个初始仓库

tsx
import { create } from 'zustand'

interface StoreState {
  count: number
  increment: () => void
  decrement: () => void
  reset: () => void
}

export const useStore = create<StoreState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}))

在页面中使用

tsx
function Counter() {
  const { count, increment, decrement, reset } = useStore()

  return (
    <div className="counter-section">
      <h1>Zustand Counter</h1>
      <div className="count-display">{count}</div>
      <div className="button-group">
        <button onClick={decrement}>-</button>
        <button onClick={reset}>Reset</button>
        <button onClick={increment}>+</button>
      </div>
    </div>
  )
}

更新状态

使用Actions方式更新状态

tsx
export const usePermissionsStore = create<PermissionsStore>((set, _, store) => ({
  permissions: ['read', 'write'],
  actions: {
    addPermission: (permission: string) =>
      set((state) => ({
        permissions: [...state.permissions, permission]
      })),
    removePermission: (permission: string) =>
      set((state) => ({
        permissions: state.permissions.filter((p) => p !== permission)
      }))
  },
  reset: () => {
    set(store.getInitialState())
  }
}))

把所有 actions 放进一个稳定对象。这样可以让你的 store 更干净、更稳定。

获取状态

直接获取

const { actions, permissions, reset} = usePermissionsStore()

通过selector获取

tsx
// 在store导出selector方式
export const usePermissions = () => usePermissionsStore((state) => state.permissions)

导入使用:const permissions = usePermissions()

重置状态

重置单个状态

tsx
reset: () => {
	set(store.getInitialState())
}

声明一个reset方法可以对状态进行初始化重置

重置所有状态

通过重写create方法实现

tsx
import { create as actualCreate, type StateCreator } from 'zustand'

const storeResetFns = new Set<() => void>()

export const create = <T>(createState: StateCreator<T>) => {
  const store = actualCreate(createState)
  const initialState = store.getState()
  storeResetFns.add(() => store.setState(initialState, true))
  return store
}

export const resetAllStores = () => {
  storeResetFns.forEach((resetFn) => resetFn())
}

持久化存储

persist 中间件允许你在页面重新加载或应用重新启动时保留存储的状态。

const nextStateCreatorFn = persist(stateCreatorFn, persistOptions)
  • stateCreatorFn:以 set 函数、get 函数和 store 作为参数的函数。通常,你将返回一个包含要公开的方法的对象。
  • persistOptions:定义存储选项的对象。
    • name:存储中存储项目的唯一名称。
    • 可选 storage:默认为 createJSONStorage(() => localStorage)
    • 可选 partialize:在持久化之前过滤状态字段的函数。
    • 可选 onRehydrateStorage:返回允许在状态补液之前和之后自定义逻辑的函数或函数。
    • 可选 version:持久状态的版本号。如果存储的状态版本不匹配,则不会使用它。
    • 可选 migrate:如果发生版本不匹配,则迁移持久状态的函数。
    • 可选 merge:在补液期间将持久状态与当前状态合并时的自定义逻辑函数。默认为浅合并。
    • 可选 skipHydration:默认为 false。如果是 true,中间件将不会在初始化时自动重新补充状态。在这种情况下手动使用 rehydrate 函数。这对于服务器端渲染 (SSR) 应用很有用。

persist 返回状态创建器函数。

示例:

tsx
const permissionStateCreatorFn: StateCreator<PermissionsStore> = (set, _, store) => ({
  permissions: ['read', 'write'],
  state: false,
  actions: {
    addPermission: (permission: string) =>
      set((state) => ({
        permissions: [...state.permissions, permission]
      })),
    removePermission: (permission: string) =>
      set((state) => ({
        permissions: state.permissions.filter((p) => p !== permission)
      }))
  },
  reset: () => {
    set(store.getInitialState())
  }
})

export const usePermissionsStore = create<PermissionsStore>(
  persist(
    permissionStateCreatorFn,
    {
      name: 'permissions-storage',
      partialize: (state) => ({ permissions: state.permissions, state: state.state }),
    }
  )
)
React状态管理:Zustand | Kailiming Blog