ahooks-v3

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Skill: ahooks

Skill: ahooks

Scope

范围

  • Applies to: ahooks v3+ utility hooks for React state management, grouped state updates, localStorage persistence
  • Does NOT cover: Data fetching (use TanStack Query), URL state management (use nuqs), complex state machines, async operations
  • 适用于:ahooks v3+ 中用于 React 状态管理、分组状态更新和 localStorage 持久化的实用 hooks
  • 不涵盖:数据获取(使用 TanStack Query)、URL 状态管理(使用 nuqs)、复杂状态机、异步操作

Assumptions

前提条件

  • ahooks v3+
  • React 18+ with hooks support
  • TypeScript v5+ (for type inference)
  • Client-side only (hooks require browser APIs for localStorage)
  • ahooks v3+
  • React 18+,支持 hooks
  • TypeScript v5+(用于类型推断)
  • 仅限客户端(hooks 需要浏览器 API 才能使用 localStorage)

Principles

原则

  • Use
    useSetState
    for grouped state that changes together (not URL-shareable)
  • Use
    useLocalStorageState
    for persistent state across browser sessions
  • Prefer nuqs for URL-shareable state over localStorage
  • Prefer TanStack Query for async operations and loading states
  • Use
    useState
    only for simple independent state (rare)
  • 对于需要共同更新的分组状态(而非可通过 URL 分享的状态),使用
    useSetState
  • 对于需要跨浏览器会话持久化的状态,使用
    useLocalStorageState
  • 对于可通过 URL 分享的状态,优先使用 nuqs 而不是 localStorage
  • 对于异步操作和加载状态,优先使用 TanStack Query
  • 仅对简单、独立的状态使用
    useState
    (很少使用)

Constraints

约束

MUST

必须

  • Use
    useSetState
    for grouped state not in URL (form state, game engine state, ephemeral UI state)
  • Use
    useLocalStorageState
    for localStorage persistence
  • 对于不在 URL 中共享、需要共同更新的分组状态,使用
    useSetState
    (表单状态、游戏引擎状态、临时 UI 状态)
  • 对于 localStorage 持久化,使用
    useLocalStorageState

SHOULD

应该

  • Prefer nuqs for URL-shareable state over localStorage
  • Prefer TanStack Query for async operations and loading states
  • Use TypeScript generics for type-safe state:
    useLocalStorageState<boolean>('key', { defaultValue: false })
  • 对于可通过 URL 分享的状态,优先使用 nuqs 而不是 localStorage
  • 对于异步操作和加载状态,优先使用 TanStack Query
  • 使用 TypeScript 泛型实现类型安全的状态:
    useLocalStorageState<boolean>('key', { defaultValue: false })

AVOID

避免

  • Using for URL state (use nuqs instead)
  • Using for loading/error states (use TanStack Query instead)
  • Using for complex async operations (use TanStack Query instead)
  • Mixing URL state with localStorage without explicit sync logic
  • 用于 URL 状态(应改用 nuqs)
  • 用于加载或错误状态(应改用 TanStack Query)
  • 用于复杂的异步操作(应改用 TanStack Query)
  • 在没有明确同步逻辑的情况下混用 URL 状态和 localStorage

Interactions

交互关系

  • Complements nuqs-v2 for URL state management (can sync bidirectionally)
  • Complements TanStack Query for async operations (use TanStack Query for data fetching)
  • Part of state management decision tree (see React rules)
  • Works with React 18+ hooks architecture
  • 与 nuqs-v2 互补,用于 URL 状态管理(可双向同步)
  • 与 TanStack Query 互补,用于异步操作(使用 TanStack Query 获取数据)
  • 属于状态管理决策树的一部分(参见 React rules)
  • 适用于 React 18+ hooks 架构

Patterns

模式

useSetState Pattern

useSetState 模式

Use for grouped state that updates together:
typescript
import { useSetState } from 'ahooks'

const [state, setState] = useSetState({
  name: '',
  email: '',
  age: 0,
})

// Partial updates (shallow merge)
setState({ name: 'John' })
setState(prev => ({ ...prev, email: 'john@example.com' }))
When to use: Form state, game engine state, UI state that changes together (if not URL-shareable)
When NOT to use: URL-shareable state (use nuqs), loading states (use TanStack Query)
用于需要共同更新的分组状态:
typescript
import { useSetState } from 'ahooks'

const [state, setState] = useSetState({
  name: '',
  email: '',
  age: 0,
})

// Partial updates (shallow merge)
setState({ name: 'John' })
setState(prev => ({ ...prev, email: 'john@example.com' }))
何时使用:表单状态、游戏引擎状态、需要共同更新的 UI 状态(如果不可通过 URL 分享)
何时不应使用:可通过 URL 分享的状态(使用 nuqs)、加载状态(使用 TanStack Query)

useLocalStorageState Pattern

useLocalStorageState 模式

Use for state that persists across browser sessions:
typescript
import { useLocalStorageState } from 'ahooks'

const [value, setValue] = useLocalStorageState<boolean>('key', {
  defaultValue: false,
})

// Type-safe with generics
const [settings, setSettings] = useLocalStorageState<Settings>('settings', {
  defaultValue: { theme: 'light', fontSize: 14 },
})
When to use: User preferences, debug flags, settings that should persist across sessions
When NOT to use: URL-shareable state (use nuqs), sensitive data (use secure storage)
用于需要跨浏览器会话持久化的状态:
typescript
import { useLocalStorageState } from 'ahooks'

const [value, setValue] = useLocalStorageState<boolean>('key', {
  defaultValue: false,
})

// Type-safe with generics
const [settings, setSettings] = useLocalStorageState<Settings>('settings', {
  defaultValue: { theme: 'light', fontSize: 14 },
})
何时使用:用户偏好、调试开关、应跨会话持久化的设置
何时不应使用:可通过 URL 分享的状态(使用 nuqs)、敏感数据(使用安全存储)

Integration with nuqs

与 nuqs 集成

Bidirectional sync between URL and localStorage:
typescript
import { useLocalStorageState } from 'ahooks'
import { useQueryState } from 'nuqs'
import { useEffect, useRef } from 'react'

const [queryState, setQueryState] = useQueryState('debug')
const [storageState, setStorageState] = useLocalStorageState<boolean>('debug', {
  defaultValue: false,
})
const isFirstMount = useRef(true)

// Sync on mount: localStorage → URL
useEffect(() => {
  if (isFirstMount.current) {
    isFirstMount.current = false
    if (storageState && queryState !== 'true') {
      setQueryState('true')
      return
    }
  }
  // Sync changes: URL → localStorage
  if (queryState === 'true' && !storageState) {
    setStorageState(true)
  } else if (queryState === 'false' && storageState) {
    setStorageState(false)
  }
}, [queryState, storageState, setQueryState, setStorageState])
Use case: Debug flags, feature toggles that should be both URL-shareable and persistent
URL 与 localStorage 之间的双向同步:
typescript
import { useLocalStorageState } from 'ahooks'
import { useQueryState } from 'nuqs'
import { useEffect, useRef } from 'react'

const [queryState, setQueryState] = useQueryState('debug')
const [storageState, setStorageState] = useLocalStorageState<boolean>('debug', {
  defaultValue: false,
})
const isFirstMount = useRef(true)

// Sync on mount: localStorage → URL
useEffect(() => {
  if (isFirstMount.current) {
    isFirstMount.current = false
    if (storageState && queryState !== 'true') {
      setQueryState('true')
      return
    }
  }
  // Sync changes: URL → localStorage
  if (queryState === 'true' && !storageState) {
    setStorageState(true)
  } else if (queryState === 'false' && storageState) {
    setStorageState(false)
  }
}, [queryState, storageState, setQueryState, setStorageState])
使用场景:既需要可通过 URL 分享,又需要持久化的调试开关和功能开关

State Management Decision Tree

状态管理决策树

  1. URL-shareable state → Use
    nuqs
    (filters, search, tabs, pagination)
  2. Grouped state not in URL → Use
    useSetState
    (form state, game engine, ephemeral UI)
  3. Async operations → Use TanStack Query (data fetching, mutations, caching)
  4. localStorage persistence → Use
    useLocalStorageState
    (preferences, settings)
  5. Simple independent state → Use
    useState
    (rare, prefer other options)
  1. 可通过 URL 分享的状态 → 使用
    nuqs
    (筛选器、搜索、标签页、分页)
  2. 不在 URL 中共享、需要共同更新的状态 → 使用
    useSetState
    (表单状态、游戏引擎、临时 UI)
  3. 异步操作 → 使用 TanStack Query(数据获取、数据变更、缓存)
  4. localStorage 持久化 → 使用
    useLocalStorageState
    (偏好、设置)
  5. 简单、独立的状态 → 使用
    useState
    (很少使用,优先考虑其他方案)

References

参考资料

  • ahooks documentation - Official documentation
  • React rules - State management decision tree and patterns
  • TanStack Query - Async operations and data fetching patterns
  • ahooks 文档 - 官方文档
  • React rules - 状态管理决策树和模式
  • TanStack Query - 异步操作和数据获取模式