tanstack-query
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTanStack Query (React Query) v5
TanStack Query (React Query) v5
Powerful asynchronous state management for React. TanStack Query makes fetching, caching, synchronizing, and updating server state in your React applications a breeze.
为React提供强大的异步状态管理能力。TanStack Query让React应用中的数据获取、缓存、同步及服务端状态更新变得轻而易举。
When to Use This Skill
何时使用该工具
- Fetching data from REST APIs or GraphQL endpoints
- Managing server state and cache lifecycle
- Implementing mutations (create, update, delete operations)
- Building infinite scroll or load-more patterns
- Handling optimistic UI updates
- Synchronizing data across components
- Implementing background data refetching
- Managing complex async state without Redux or other state managers
- 从REST API或GraphQL端点获取数据
- 管理服务端状态与缓存生命周期
- 实现变更操作(创建、更新、删除)
- 构建无限滚动或加载更多模式
- 处理乐观UI更新
- 跨组件同步数据
- 实现后台数据重新获取
- 无需Redux或其他状态管理器即可管理复杂异步状态
Quick Start Workflow
快速开始流程
1. Installation
1. 安装
bash
npm install @tanstack/react-querybash
npm install @tanstack/react-queryor
or
pnpm add @tanstack/react-query
pnpm add @tanstack/react-query
or
or
yarn add @tanstack/react-query
undefinedyarn add @tanstack/react-query
undefined2. Setup QueryClient
2. 配置QueryClient
Wrap your application with :
QueryClientProvidertsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
</QueryClientProvider>
);
}使用包裹你的应用:
QueryClientProvidertsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
</QueryClientProvider>
);
}3. Basic Query
3. 基础查询
tsx
import { useQuery } from '@tanstack/react-query';
function TodoList() {
const { data, isLoading, error } = useQuery({
queryKey: ['todos'],
queryFn: async () => {
const res = await fetch('https://api.example.com/todos');
if (!res.ok) throw new Error('Network response was not ok');
return res.json();
},
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}tsx
import { useQuery } from '@tanstack/react-query';
function TodoList() {
const { data, isLoading, error } = useQuery({
queryKey: ['todos'],
queryFn: async () => {
const res = await fetch('https://api.example.com/todos');
if (!res.ok) throw new Error('Network response was not ok');
return res.json();
},
});
if (isLoading) return <div>加载中...</div>;
if (error) return <div>错误:{error.message}</div>;
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}4. Basic Mutation
4. 基础变更
tsx
import { useMutation, useQueryClient } from '@tanstack/react-query';
function CreateTodo() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: async (newTodo) => {
const res = await fetch('https://api.example.com/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
headers: { 'Content-Type': 'application/json' },
});
return res.json();
},
onSuccess: () => {
// Invalidate and refetch todos
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});
return (
<button onClick={() => mutation.mutate({ title: 'New Todo' })}>
{mutation.isPending ? 'Creating...' : 'Create Todo'}
</button>
);
}tsx
import { useMutation, useQueryClient } from '@tanstack/react-query';
function CreateTodo() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: async (newTodo) => {
const res = await fetch('https://api.example.com/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
headers: { 'Content-Type': 'application/json' },
});
return res.json();
},
onSuccess: () => {
// 失效并重新获取todos数据
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});
return (
<button onClick={() => mutation.mutate({ title: 'New Todo' })}>
{mutation.isPending ? '创建中...' : '创建待办事项'}
</button>
);
}Core Concepts
核心概念
Query Keys
查询键(Query Keys)
Query keys uniquely identify queries and are used for caching. They must be arrays.
tsx
// Simple key
useQuery({ queryKey: ['todos'], queryFn: fetchTodos });
// Key with variables
useQuery({ queryKey: ['todo', todoId], queryFn: () => fetchTodo(todoId) });
// Hierarchical keys
useQuery({ queryKey: ['todos', 'list', { filters, page }], queryFn: fetchTodos });Query key matching:
- - exact match
['todos'] - - exact match with object
['todos', { page: 1 }] - - matches all queries starting with 'todos'
{ queryKey: ['todos'] }
查询键用于唯一标识查询,是缓存的依据,必须为数组格式。
tsx
// 简单键
useQuery({ queryKey: ['todos'], queryFn: fetchTodos });
// 带变量的键
useQuery({ queryKey: ['todo', todoId], queryFn: () => fetchTodo(todoId) });
// 层级键
useQuery({ queryKey: ['todos', 'list', { filters, page }], queryFn: fetchTodos });查询键匹配规则:
- - 精确匹配
['todos'] - - 包含对象的精确匹配
['todos', { page: 1 }] - - 匹配所有以'todos'开头的查询
{ queryKey: ['todos'] }
Query Functions
查询函数(Query Functions)
Query functions must return a promise that resolves data or throws an error:
tsx
// Using fetch
queryFn: async () => {
const res = await fetch(url);
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
}
// Using axios
queryFn: () => axios.get(url).then(res => res.data)
// With query key access
queryFn: ({ queryKey }) => {
const [_, todoId] = queryKey;
return fetchTodo(todoId);
}查询函数必须返回一个Promise,该Promise需解析数据或抛出错误:
tsx
// 使用fetch
queryFn: async () => {
const res = await fetch(url);
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
}
// 使用axios
queryFn: () => axios.get(url).then(res => res.data)
// 访问查询键
queryFn: ({ queryKey }) => {
const [_, todoId] = queryKey;
return fetchTodo(todoId);
}Important Defaults
重要默认配置
Understanding defaults is crucial for optimal usage:
- staleTime: 0 - Queries become stale immediately by default
- gcTime: 5 minutes - Unused/inactive cache data remains in memory for 5 minutes
- retry: 3 - Failed queries retry 3 times with exponential backoff
- refetchOnWindowFocus: true - Queries refetch when window regains focus
- refetchOnReconnect: true - Queries refetch when network reconnects
tsx
// Override defaults globally
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
gcTime: 1000 * 60 * 10, // 10 minutes
},
},
});
// Or per query
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
staleTime: 1000 * 60, // 1 minute
retry: 5,
});理解默认配置对优化使用至关重要:
- staleTime: 0 - 默认情况下,查询结果会立即变为“过时”状态
- gcTime: 5分钟 - 未使用/非活跃的缓存数据会在内存中保留5分钟
- retry: 3 - 失败的查询会自动重试3次,采用指数退避策略
- refetchOnWindowFocus: true - 当窗口重新获得焦点时,会重新获取查询数据
- refetchOnReconnect: true - 网络重新连接时,会重新获取查询数据
tsx
// 全局覆盖默认配置
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5分钟
gcTime: 1000 * 60 * 10, // 10分钟
},
},
});
// 或针对单个查询配置
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
staleTime: 1000 * 60, // 1分钟
retry: 5,
});Query Status and Fetch Status
查询状态与获取状态
Queries have two important states:
Query Status:
- - No cached data, query is executing
pending - - Query encountered an error
error - - Query succeeded and data is available
success
Fetch Status:
- - Query function is executing
fetching - - Query wants to fetch but is paused (offline)
paused - - Query is not fetching
idle
tsx
const { data, status, fetchStatus, isLoading, isFetching } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});
// isLoading = status === 'pending'
// isFetching = fetchStatus === 'fetching'查询包含两个重要状态:
查询状态:
- - 无缓存数据,查询正在执行
pending - - 查询遇到错误
error - - 查询成功,数据可用
success
获取状态:
- - 查询函数正在执行
fetching - - 查询需要执行但已暂停(离线状态)
paused - - 查询未在执行
idle
tsx
const { data, status, fetchStatus, isLoading, isFetching } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});
// isLoading = status === 'pending'
// isFetching = fetchStatus === 'fetching'Query Invalidation
查询失效
Mark queries as stale to trigger refetches:
tsx
const queryClient = useQueryClient();
// Invalidate all todos queries
queryClient.invalidateQueries({ queryKey: ['todos'] });
// Invalidate specific query
queryClient.invalidateQueries({ queryKey: ['todo', todoId] });
// Invalidate and refetch immediately
queryClient.invalidateQueries({
queryKey: ['todos'],
refetchType: 'active' // only refetch active queries
});将查询标记为过时以触发重新获取:
tsx
const queryClient = useQueryClient();
// 使所有todos查询失效
queryClient.invalidateQueries({ queryKey: ['todos'] });
// 使特定查询失效
queryClient.invalidateQueries({ queryKey: ['todo', todoId] });
// 使查询失效并立即重新获取
queryClient.invalidateQueries({
queryKey: ['todos'],
refetchType: 'active' // 仅重新获取活跃的查询
});Mutations
变更操作(Mutations)
Mutations are used for creating, updating, or deleting data:
tsx
const mutation = useMutation({
mutationFn: (newTodo) => {
return fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
});
},
onSuccess: (data, variables, context) => {
console.log('Success!', data);
},
onError: (error, variables, context) => {
console.error('Error:', error);
},
onSettled: (data, error, variables, context) => {
console.log('Mutation finished');
},
});
// Trigger mutation
mutation.mutate({ title: 'New Todo' });
// With async/await
mutation.mutateAsync({ title: 'New Todo' })
.then(data => console.log(data))
.catch(error => console.error(error));变更操作用于创建、更新或删除数据:
tsx
const mutation = useMutation({
mutationFn: (newTodo) => {
return fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
});
},
onSuccess: (data, variables, context) => {
console.log('成功!', data);
},
onError: (error, variables, context) => {
console.error('错误:', error);
},
onSettled: (data, error, variables, context) => {
console.log('变更操作完成');
},
});
// 触发变更
mutation.mutate({ title: 'New Todo' });
// 使用async/await
mutation.mutateAsync({ title: 'New Todo' })
.then(data => console.log(data))
.catch(error => console.error(error));React Suspense Integration
React Suspense集成
TanStack Query supports React Suspense with dedicated hooks:
tsx
import { useSuspenseQuery } from '@tanstack/react-query';
function TodoList() {
// This will suspend the component until data is ready
const { data } = useSuspenseQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});
// No need for loading states - handled by Suspense boundary
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
// In parent component
function App() {
return (
<Suspense fallback={<div>Loading todos...</div>}>
<TodoList />
</Suspense>
);
}TanStack Query通过专用钩子支持React Suspense:
tsx
import { useSuspenseQuery } from '@tanstack/react-query';
function TodoList() {
// 组件会挂起直到数据准备完成
const { data } = useSuspenseQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});
// 无需处理加载状态 - 由Suspense边界处理
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
// 在父组件中
function App() {
return (
<Suspense fallback={<div>加载待办事项...</div>}>
<TodoList />
</Suspense>
);
}Advanced Topics
高级主题
For detailed information on advanced patterns, see the reference files:
如需了解高级模式的详细信息,请参考参考文档:
Infinite Queries
无限查询
For implementing infinite scroll and load-more patterns:
- See for comprehensive guide
references/infinite-queries.md - Covers hook
useInfiniteQuery - Bidirectional pagination
- and
getNextPageParamgetPreviousPageParam - Refetching and background updates
用于实现无限滚动和加载更多模式:
- 查看获取完整指南
references/infinite-queries.md - 涵盖钩子
useInfiniteQuery - 双向分页
- 和
getNextPageParamgetPreviousPageParam - 重新获取与后台更新
Optimistic Updates
乐观更新
For updating UI before server confirmation:
- See for detailed patterns
references/optimistic-updates.md - Optimistic mutations
- Rollback on error
- Context for cancellation
- UI feedback strategies
在服务器确认前更新UI:
- 查看获取详细模式
references/optimistic-updates.md - 乐观变更
- 错误时回滚
- 取消操作的上下文
- UI反馈策略
TypeScript Support
TypeScript支持
For full type safety and inference:
- See for complete TypeScript guide
references/typescript.md - Type inference from query functions
- Generic type parameters
- Typing query options
- Custom hooks with types
- Error type narrowing
实现完整的类型安全与类型推断:
- 查看获取完整TypeScript指南
references/typescript.md - 从查询函数进行类型推断
- 泛型类型参数
- 为查询选项添加类型
- 带类型的自定义钩子
- 错误类型收窄
Query Invalidation Patterns
查询失效模式
For advanced cache invalidation strategies:
- See
references/query-invalidation.md - Partial matching
- Predicate functions
- Refetch strategies
- Query filters
高级缓存失效策略:
- 查看
references/query-invalidation.md - 部分匹配
- 谓词函数
- 重新获取策略
- 查询过滤器
Performance Optimization
性能优化
For optimizing query performance:
- See
references/performance.md - Query deduplication
- Structural sharing
- Memory management
- Query splitting strategies
优化查询性能:
- 查看
references/performance.md - 查询去重
- 结构共享
- 内存管理
- 查询拆分策略
DevTools
开发工具(DevTools)
TanStack Query DevTools provide visual insights into query state:
bash
npm install @tanstack/react-query-devtoolstsx
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}DevTools features:
- View all queries and their states
- Inspect query data and errors
- Manually trigger refetches
- Invalidate queries
- Monitor cache lifecycle
TanStack Query DevTools提供查询状态的可视化洞察:
bash
npm install @tanstack/react-query-devtoolstsx
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourApp />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}DevTools功能:
- 查看所有查询及其状态
- 检查查询数据与错误
- 手动触发重新获取
- 使查询失效
- 监控缓存生命周期
Common Patterns
常见模式
Dependent Queries
依赖查询
Run queries in sequence when one depends on another:
tsx
// First query
const { data: user } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
});
// Second query depends on first
const { data: projects } = useQuery({
queryKey: ['projects', user?.id],
queryFn: () => fetchProjects(user.id),
enabled: !!user?.id, // Only run when user.id is available
});当一个查询依赖另一个查询时,按顺序执行:
tsx
// 第一个查询
const { data: user } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
});
// 第二个查询依赖第一个查询的结果
const { data: projects } = useQuery({
queryKey: ['projects', user?.id],
queryFn: () => fetchProjects(user.id),
enabled: !!user?.id, // 仅当user.id可用时执行
});Parallel Queries
并行查询
Multiple independent queries in one component:
tsx
function Dashboard() {
const users = useQuery({ queryKey: ['users'], queryFn: fetchUsers });
const posts = useQuery({ queryKey: ['posts'], queryFn: fetchPosts });
const stats = useQuery({ queryKey: ['stats'], queryFn: fetchStats });
if (users.isLoading || posts.isLoading || stats.isLoading) {
return <div>Loading...</div>;
}
// All queries succeeded
return <DashboardView users={users.data} posts={posts.data} stats={stats.data} />;
}在一个组件中执行多个独立查询:
tsx
function Dashboard() {
const users = useQuery({ queryKey: ['users'], queryFn: fetchUsers });
const posts = useQuery({ queryKey: ['posts'], queryFn: fetchPosts });
const stats = useQuery({ queryKey: ['stats'], queryFn: fetchStats });
if (users.isLoading || posts.isLoading || stats.isLoading) {
return <div>加载中...</div>;
}
// 所有查询成功
return <DashboardView users={users.data} posts={posts.data} stats={stats.data} />;
}Dynamic Parallel Queries
动态并行查询
Use for dynamic number of queries:
useQueriestsx
import { useQueries } from '@tanstack/react-query';
function TodoLists({ listIds }) {
const results = useQueries({
queries: listIds.map((id) => ({
queryKey: ['list', id],
queryFn: () => fetchList(id),
})),
});
const isLoading = results.some(result => result.isLoading);
const data = results.map(result => result.data);
return <Lists data={data} />;
}使用处理动态数量的查询:
useQueriestsx
import { useQueries } from '@tanstack/react-query';
function TodoLists({ listIds }) {
const results = useQueries({
queries: listIds.map((id) => ({
queryKey: ['list', id],
queryFn: () => fetchList(id),
})),
});
const isLoading = results.some(result => result.isLoading);
const data = results.map(result => result.data);
return <Lists data={data} />;
}Prefetching
预获取
Prefetch data before it's needed:
tsx
const queryClient = useQueryClient();
// Prefetch on hover
function TodoListLink({ id }) {
const prefetch = () => {
queryClient.prefetchQuery({
queryKey: ['todo', id],
queryFn: () => fetchTodo(id),
staleTime: 1000 * 60 * 5, // Cache for 5 minutes
});
};
return (
<Link to={`/todo/${id}`} onMouseEnter={prefetch}>
View Todo
</Link>
);
}在需要数据之前提前获取:
tsx
const queryClient = useQueryClient();
// 鼠标悬停时预获取
function TodoListLink({ id }) {
const prefetch = () => {
queryClient.prefetchQuery({
queryKey: ['todo', id],
queryFn: () => fetchTodo(id),
staleTime: 1000 * 60 * 5, // 缓存5分钟
});
};
return (
<Link to={`/todo/${id}`} onMouseEnter={prefetch}>
查看待办事项
</Link>
);
}Initial Data
初始数据
Provide initial data to avoid loading states:
tsx
function TodoDetail({ todoId, initialTodo }) {
const { data } = useQuery({
queryKey: ['todo', todoId],
queryFn: () => fetchTodo(todoId),
initialData: initialTodo, // Use this data immediately
staleTime: 1000 * 60, // Consider fresh for 1 minute
});
return <div>{data.title}</div>;
}提供初始数据以避免加载状态:
tsx
function TodoDetail({ todoId, initialTodo }) {
const { data } = useQuery({
queryKey: ['todo', todoId],
queryFn: () => fetchTodo(todoId),
initialData: initialTodo, // 立即使用该数据
staleTime: 1000 * 60, // 1分钟内视为新鲜数据
});
return <div>{data.title}</div>;
}Placeholder Data
占位数据
Show placeholder while loading:
tsx
const { data, isPlaceholderData } = useQuery({
queryKey: ['todos', page],
queryFn: () => fetchTodos(page),
placeholderData: (previousData) => previousData, // Keep previous data while loading
});
// Or use static placeholder
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
placeholderData: { items: [], total: 0 },
});加载过程中显示占位内容:
tsx
const { data, isPlaceholderData } = useQuery({
queryKey: ['todos', page],
queryFn: () => fetchTodos(page),
placeholderData: (previousData) => previousData, // 加载时保留之前的数据
});
// 或使用静态占位数据
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
placeholderData: { items: [], total: 0 },
});Error Handling
错误处理
Query Errors
查询错误
tsx
const { error, isError } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
retry: 3,
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
});
if (isError) {
return <div>Error: {error.message}</div>;
}tsx
const { error, isError } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
retry: 3,
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
});
if (isError) {
return <div>错误:{error.message}</div>;
}Global Error Handling
全局错误处理
tsx
const queryClient = new QueryClient({
defaultOptions: {
queries: {
onError: (error) => {
console.error('Query error:', error);
// Show toast notification, etc.
},
},
mutations: {
onError: (error) => {
console.error('Mutation error:', error);
},
},
},
});tsx
const queryClient = new QueryClient({
defaultOptions: {
queries: {
onError: (error) => {
console.error('查询错误:', error);
// 显示提示通知等
},
},
mutations: {
onError: (error) => {
console.error('变更错误:', error);
},
},
},
});Error Boundaries
错误边界
Combine with React Error Boundaries:
tsx
import { useQuery } from '@tanstack/react-query';
import { ErrorBoundary } from 'react-error-boundary';
function TodoList() {
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
throwOnError: true, // Throw errors to error boundary
});
return <div>{/* render data */}</div>;
}
function App() {
return (
<ErrorBoundary fallback={<div>Something went wrong</div>}>
<TodoList />
</ErrorBoundary>
);
}与React错误边界结合使用:
tsx
import { useQuery } from '@tanstack/react-query';
import { ErrorBoundary } from 'react-error-boundary';
function TodoList() {
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
throwOnError: true, // 将错误抛给错误边界
});
return <div>{/* 渲染数据 */}</div>;
}
function App() {
return (
<ErrorBoundary fallback={<div>出现错误</div>}>
<TodoList />
</ErrorBoundary>
);
}Best Practices
最佳实践
-
Use Query Keys Wisely
- Structure keys hierarchically:
['todos', 'list', { filters }] - Include all variables in the key
- Keep keys consistent across your app
- Structure keys hierarchically:
-
Set Appropriate staleTime
- Static data:
staleTime: Infinity - Frequently changing: (default)
staleTime: 0 - Moderately changing: (5 minutes)
staleTime: 1000 * 60 * 5
- Static data:
-
Handle Loading and Error States
- Always check and
isLoadingerror - Provide meaningful loading indicators
- Show user-friendly error messages
- Always check
-
Optimize Refetching
- Disable unnecessary refetches with
refetchOnWindowFocus: false - Use to reduce refetches
staleTime - Consider using for polling
refetchInterval
- Disable unnecessary refetches with
-
Invalidate Efficiently
- Invalidate specific queries, not all queries
- Use query key prefixes for related queries
- Combine with optimistic updates for better UX
-
Use TypeScript
- Type your query functions for type inference
- Use generic type parameters when needed
- Enable strict type checking
-
Leverage DevTools
- Install DevTools in development
- Monitor query behavior
- Debug cache issues
-
合理使用查询键
- 采用层级结构:
['todos', 'list', { filters }] - 将所有变量包含在查询键中
- 在应用中保持查询键的一致性
- 采用层级结构:
-
设置合适的staleTime
- 静态数据:
staleTime: Infinity - 频繁变化的数据:(默认值)
staleTime: 0 - 中等频率变化的数据:(5分钟)
staleTime: 1000 * 60 * 5
- 静态数据:
-
处理加载与错误状态
- 始终检查和
isLoading状态error - 提供有意义的加载指示器
- 显示用户友好的错误信息
- 始终检查
-
优化重新获取策略
- 通过禁用不必要的重新获取
refetchOnWindowFocus: false - 使用减少重新获取次数
staleTime - 考虑使用进行轮询
refetchInterval
- 通过
-
高效失效查询
- 使特定查询失效,而非所有查询
- 为相关查询使用查询键前缀
- 结合乐观更新以提升用户体验
-
使用TypeScript
- 为查询函数添加类型以实现类型推断
- 必要时使用泛型类型参数
- 启用严格类型检查
-
利用开发工具
- 在开发环境中安装DevTools
- 监控查询行为
- 调试缓存问题
Resources
资源
- Official Documentation: https://tanstack.com/query/latest/docs/framework/react/overview
- GitHub Repository: https://github.com/TanStack/query
- Examples: https://tanstack.com/query/latest/docs/framework/react/examples
- Community: https://discord.gg/tanstack
- TypeScript Guide: https://tanstack.com/query/latest/docs/framework/react/typescript
Migration from v4
从v4迁移
If you're upgrading from React Query v4:
- renamed to
cacheTimegcTime - pageParam changes
useInfiniteQuery - New hooks
useSuspenseQuery - Improved TypeScript inference
- See official migration guide: https://tanstack.com/query/latest/docs/framework/react/guides/migrating-to-v5
如果你正在从React Query v4升级:
- 重命名为
cacheTimegcTime - 的pageParam发生变化
useInfiniteQuery - 新增钩子
useSuspenseQuery - 改进了TypeScript推断
- 查看官方迁移指南:https://tanstack.com/query/latest/docs/framework/react/guides/migrating-to-v5