React Query 服务端状态
约 474 字大约 2 分钟
布欧-Lewyon
2026-05-15
React Query(TanStack Query)管理服务端状态——数据获取、缓存、同步更新。
安装
npm install @tanstack/react-query// main.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const queryClient = new QueryClient()
ReactDOM.createRoot(document.getElementById('root')!).render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
)useQuery
import { useQuery } from '@tanstack/react-query'
function UserList() {
const { data, isLoading, error, refetch } = useQuery({
queryKey: ['users'], // 唯一 key,用于缓存
queryFn: () => fetch('/api/users').then(r => r.json()),
staleTime: 30_000, // 30 秒内不重新请求
cacheTime: 5 * 60_000, // 5 分钟缓存
})
if (isLoading) return <div>加载中...</div>
if (error) return <div>错误: {error.message}</div>
return (
<div>
<button onClick={() => refetch()}>刷新</button>
{data.map(user => <div key={user.id}>{user.name}</div>)}
</div>
)
}useMutation
import { useMutation, useQueryClient } from '@tanstack/react-query'
function AddUser() {
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: (newUser: { name: string }) =>
fetch('/api/users', {
method: 'POST',
body: JSON.stringify(newUser),
headers: { 'Content-Type': 'application/json' }
}),
onSuccess: () => {
// 成功后重新拉取用户列表
queryClient.invalidateQueries({ queryKey: ['users'] })
},
})
return (
<div>
<button
onClick={() => mutation.mutate({ name: 'New User' })}
disabled={mutation.isPending}
>
{mutation.isPending ? '添加中...' : '添加用户'}
</button>
{mutation.isError && <p>添加失败: {mutation.error.message}</p>}
</div>
)
}乐观更新
const mutation = useMutation({
mutationFn: updatedTodo => fetch(`/api/todos/${updatedTodo.id}`, {
method: 'PUT',
body: JSON.stringify(updatedTodo),
}),
onMutate: async (updatedTodo) => {
// 1. 取消正在进行的查询
await queryClient.cancelQueries({ queryKey: ['todos'] })
// 2. 保存当前缓存快照
const previous = queryClient.getQueryData(['todos'])
// 3. 乐观更新缓存
queryClient.setQueryData(['todos'], old =>
old.map(t => t.id === updatedTodo.id ? updatedTodo : t)
)
// 4. 返回回滚函数
return { previous }
},
onError: (err, variables, context) => {
// 失败时回滚
queryClient.setQueryData(['todos'], context.previous)
},
})React Query vs 其他方案
| 方案 | 加载状态 | 缓存 | 重试 | 乐观更新 |
|---|---|---|---|---|
| useEffect + fetch | ❌ 手动 | ❌ | ❌ | ❌ |
| SWR | ✅ | ✅ | ✅ | ✅ |
| React Query | ✅ | ✅ | ✅ | ✅ |
| Zustand(纯服务端) | ❌ 手动 | ❌ | ❌ | ❌ |
数据获取的最佳实践:React Query(服务端状态)+ Zustand(客户端状态)。
小结
- React Query 管理服务端状态:缓存、重取、乐观更新。
useQuery获取数据,useMutation修改数据。staleTime控制缓存有效时间,避免频繁请求。invalidateQueries修改成功后刷新列表。- 乐观更新:先显式更新 UI,失败时回滚。
上一节:Zustand 轻量状态库 下一节:Redux Toolkit
