tanstack-query-hooks

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TanStack Query Hooks Builder

TanStack Query Hooks 生成器

Generate production-ready data fetching hooks using TanStack Query (React Query) v5.
使用TanStack Query (React Query) v5生成可用于生产环境的数据获取hooks。

Quick Start

快速开始

Step 1: Identify Data Type

步骤1:确定数据类型

Choose the appropriate hook pattern:
Data TypePatternUse Case
Read-only data
useQuery
Get users, get transactions, get products
Create/Update/Delete
useMutation
Create user, update transaction, delete product
Paginated lists
useInfiniteQuery
Infinite scroll, load more
Dependent queriesChained
useQuery
Fetch user → then user's posts
选择合适的hook模式:
数据类型模式使用场景
只读数据
useQuery
获取用户列表、获取交易记录、获取商品列表
创建/更新/删除
useMutation
创建用户、更新交易记录、删除商品
分页列表
useInfiniteQuery
无限滚动、加载更多
依赖查询链式
useQuery
先获取用户 → 再获取该用户的帖子

Step 2: Define Query Key Strategy

步骤2:定义查询键策略

CRITICAL: Query keys enable automatic cache invalidation.
typescript
// ✅ Hierarchical keys (RECOMMENDED)
QUERY_KEYS.users.root(estId)           // ['users', 'est-123']
QUERY_KEYS.users.detail(estId, userId) // ['users', 'est-123', 'detail', 'user-456']

// ❌ Flat keys (avoid)
['users']  // Can't target specific user
See Query Keys Architecture for centralized keys.
关键提示:查询键是自动缓存失效的基础。
typescript
// ✅ 分层键(推荐)
QUERY_KEYS.users.root(estId)           // ['users', 'est-123']
QUERY_KEYS.users.detail(estId, userId) // ['users', 'est-123', 'detail', 'user-456']

// ❌ 扁平键(不推荐)
['users']  // 无法定向失效特定用户的缓存
集中式键的定义请参考查询键架构。

Step 3: Generate Hook

步骤3:生成Hook

Provide hook specifications:
Hook: useTransacciones
Type: query
Entity: transacciones
Params: entityId
Returns: transacciones[], loading, error
Receive complete hook with:
  • TanStack Query integration
  • Automatic cache management
  • Error handling
  • TypeScript types
  • Loading/success/error states
提供hook规格说明:
Hook: useTransacciones
Type: query
Entity: transacciones
Params: entityId
Returns: transacciones[], loading, error
将获得完整的hook,包含:
  • TanStack Query 集成
  • 自动缓存管理
  • 错误处理
  • TypeScript 类型定义
  • 加载/成功/错误状态

Core Standards

核心规范

Required Imports

必需导入

typescript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { QUERY_KEYS } from '@/lib/queryKeys';
import { supabase } from '@/lib/supabase';
typescript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { QUERY_KEYS } from '@/lib/queryKeys';
import { supabase } from '@/lib/supabase';

Query Pattern

Query 模式

typescript
const { data, isLoading, error, refetch } = useQuery({
  queryKey: QUERY_KEYS.entity.root(id),
  queryFn: async () => {
    const { data, error } = await supabase
      .from('table')
      .select('*')
      .eq('id', id);

    if (error) throw error;
    return data;
  },
  enabled: !!id,  // Only run if id exists
  staleTime: 5 * 60 * 1000,  // 5 minutes
});
typescript
const { data, isLoading, error, refetch } = useQuery({
  queryKey: QUERY_KEYS.entity.root(id),
  queryFn: async () => {
    const { data, error } = await supabase
      .from('table')
      .select('*')
      .eq('id', id);

    if (error) throw error;
    return data;
  },
  enabled: !!id,  // 仅当id存在时执行查询
  staleTime: 5 * 60 * 1000,  // 5分钟
});

Mutation Pattern

Mutation 模式

typescript
const mutation = useMutation({
  mutationFn: async (data) => {
    const { data: result, error } = await supabase
      .from('table')
      .insert(data)
      .select()
      .single();

    if (error) throw error;
    return result;
  },
  onSuccess: () => {
    // ✅ CRITICAL: Invalidate related queries
    queryClient.invalidateQueries({
      queryKey: QUERY_KEYS.entity.root(id)
    });
  }
});
typescript
const mutation = useMutation({
  mutationFn: async (data) => {
    const { data: result, error } = await supabase
      .from('table')
      .insert(data)
      .select()
      .single();

    if (error) throw error;
    return result;
  },
  onSuccess: () => {
    // ✅ 关键:失效相关查询的缓存
    queryClient.invalidateQueries({
      queryKey: QUERY_KEYS.entity.root(id)
    });
  }
});

Decision Tree

决策树

When to Use useQuery

何时使用 useQuery

Use for:
  • ✅ Fetching lists (users, products, transactions)
  • ✅ Fetching single items (user detail, product detail)
  • ✅ Fetching computed data (dashboards, reports)
  • ✅ Data that changes infrequently
Benefits:
  • Automatic caching
  • Background refetching
  • Deduplication (same query = single request)
  • Optimistic UI updates
适用场景:
  • ✅ 获取列表(用户、商品、交易记录)
  • ✅ 获取单个条目(用户详情、商品详情)
  • ✅ 获取计算数据(仪表盘、报表)
  • ✅ 变更不频繁的数据
优势:
  • 自动缓存
  • 后台重新获取
  • 请求去重(相同查询仅发一次请求)
  • 乐观UI更新

When to Use useMutation

何时使用 useMutation

Use for:
  • ✅ Creating records (POST)
  • ✅ Updating records (PUT/PATCH)
  • ✅ Deleting records (DELETE)
  • ✅ Any action that modifies server state
Benefits:
  • Automatic query invalidation
  • Loading/success/error states
  • Optimistic updates support
  • Retry on failure
适用场景:
  • ✅ 创建记录(POST)
  • ✅ 更新记录(PUT/PATCH)
  • ✅ 删除记录(DELETE)
  • ✅ 任何修改服务端状态的操作
优势:
  • 自动查询缓存失效
  • 加载/成功/错误状态
  • 支持乐观更新
  • 失败重试

When to Use useState (NOT TanStack Query)

何时使用 useState(而非 TanStack Query)

Use for:
  • ✅ UI-only state (modal open/closed, selected tab)
  • ✅ Form field values (before submit)
  • ✅ Client-side filters (doesn't affect server)
Rule of Thumb:
If it comes from the server → TanStack Query If it's only UI state → useState
适用场景:
  • ✅ 纯UI状态(模态框开关、选中的标签页)
  • ✅ 表单字段值(提交前)
  • ✅ 客户端筛选(不影响服务端)
经验法则:
如果数据来自服务端 → 用 TanStack Query 如果只是UI状态 → 用 useState

Configuration

配置

Global Settings (queryClient.ts)

全局设置 (queryClient.ts)

typescript
import { QueryClient } from '@tanstack/react-query';

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000,      // 5 min cache
      gcTime: 10 * 60 * 1000,        // 10 min garbage collection
      refetchOnWindowFocus: true,    // Refetch on tab focus
      retry: 3,                      // Retry 3 times on error
      refetchOnMount: false,         // Don't refetch if cache fresh
    },
    mutations: {
      retry: 1,                      // Retry mutations once
    }
  }
});
typescript
import { QueryClient } from '@tanstack/react-query';

export const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000,      // 5分钟缓存
      gcTime: 10 * 60 * 1000,        // 10分钟垃圾回收
      refetchOnWindowFocus: true,    // 标签页获得焦点时重新获取
      retry: 3,                      // 错误时重试3次
      refetchOnMount: false,         // 缓存未过期时挂载不重新获取
    },
    mutations: {
      retry: 1,                      // mutation重试1次
    }
  }
});

DevTools (Development Only)

开发者工具(仅开发环境)

typescript
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

<QueryClientProvider client={queryClient}>
  <App />
  <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
typescript
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

<QueryClientProvider client={queryClient}>
  <App />
  <ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>

Templates

模板

Basic Query Hook

基础Query Hook

See TEMPLATES.md
请参考TEMPLATES.md

Mutation Hook with Invalidation

带缓存失效的Mutation Hook

See TEMPLATES.md
请参考TEMPLATES.md

Dependent Queries

依赖查询

See TEMPLATES.md
请参考TEMPLATES.md

Infinite Query (Pagination)

无限查询(分页)

See TEMPLATES.md
请参考TEMPLATES.md

Advanced Patterns

高级模式

Optimistic Updates

乐观更新

See PATTERNS.md
请参考PATTERNS.md

Parallel Queries

并行查询

See PATTERNS.md
请参考PATTERNS.md

Query Invalidation Strategies

查询缓存失效策略

See PATTERNS.md
请参考PATTERNS.md

Migration from Legacy Hooks

从旧版Hook迁移

If you have existing hooks using
useState
+
useEffect
:
See INTEGRATION.md for step-by-step migration guide.
如果你有使用
useState
+
useEffect
的现有hook:
请参考INTEGRATION.md获取分步迁移指南。

Checklist

检查清单

When generating TanStack Query hooks, verify:
  • Uses centralized
    QUERY_KEYS
    from
    /lib/queryKeys.ts
  • Query has appropriate
    staleTime
    (default 5 min)
  • Query uses
    enabled
    flag for conditional fetching
  • Mutation invalidates related queries in
    onSuccess
  • Error handling with proper error messages
  • TypeScript types for data and params
  • Loading states handled in component
  • Success/error notifications on mutations
生成TanStack Query hooks时,请验证:
  • 使用了
    /lib/queryKeys.ts
    中的集中式
    QUERY_KEYS
  • Query设置了合适的
    staleTime
    (默认5分钟)
  • Query使用
    enabled
    标志实现条件获取
  • Mutation在
    onSuccess
    中失效相关查询的缓存
  • 错误处理带有合适的错误信息
  • 数据和参数有TypeScript类型定义
  • 组件中处理了加载状态
  • Mutation有成功/错误通知

Anti-patterns to Avoid

需避免的反模式

  • Using useState for server data
  • Not invalidating queries after mutations
  • Missing
    enabled
    flag on conditional queries
  • Hardcoded query keys (use QUERY_KEYS)
  • Fetching in useEffect (use useQuery)
  • Not handling loading/error states
  • Refetching manually when invalidation is better
  • 用useState管理服务端数据
  • Mutation后不失效查询缓存
  • 条件查询缺少
    enabled
    标志
  • 硬编码查询键(应使用QUERY_KEYS)
  • 在useEffect中发起请求(应使用useQuery)
  • 不处理加载/错误状态
  • 可以用缓存失效时却手动重新获取

Examples

示例

Example 1: Simple List Hook

示例1:简单列表Hook

typescript
Type: query
Entity: proveedores
Params: entityId
Result: Complete hook fetching provider list with cache.
typescript
Type: query
Entity: proveedores
Params: entityId
结果:带缓存的供应商列表获取完整hook。

Example 2: Create Mutation

示例2:创建Mutation

typescript
Type: mutation
Action: createProveedor
Invalidates: proveedores list
Result: Mutation hook with auto-invalidation and loading states.
typescript
Type: mutation
Action: createProveedor
Invalidates: proveedores list
结果:带自动缓存失效和加载状态的Mutation hook。

Example 3: Detail Query with Dependencies

示例3:带依赖的详情Query

typescript
Type: query
Entity: childDetail
Params: entityId, childId
DependsOn: entityId exists
Result: Query that only runs when dependencies are met.
typescript
Type: query
Entity: childDetail
Params: entityId, childId
DependsOn: entityId exists
结果:仅在依赖满足时才执行的查询。