目录
- 前言
- 一、TanStack Query(React Query `v4+`)
- 1、从 React Query 到 TanStack Query 之间的变化
- 二、react-query 的核心 API
- 1、查询核心 API(获取服务器状态)
- (1)、useQuery() — React Query 的灵魂 API
- (2)、useInfiniteQuery() — 无限加载 / 下拉加载更多
- (3)、useSuspenseQuery() — 和 React Suspense 结合(新趋势)
- 2、Mutation 核心 API(提交数据、写入服务器)
- (1)、useMutation() — 提交数据、写操作(POST/PUT/DELETE)
- (2)、useSuspenseMutation() — Suspense 的 mutation 版本
- 3、Query Client(全局控制器)API
- (1)、queryClient.fetchQuery() — 手动触发查询(常用于 SSR)
- (2)、queryClient.invalidateQueries() — 主动重刷缓存(非常关键)
- (3)、queryClient.refetchQueries() — 主动重新获取(立即刷新)
- (4)、queryClient.setQueryData() — 手动更新缓存(无网络)
- (5)、queryClient.getQueryData() — 读取缓存(不会触发请求)
- (6)、queryClient.prefetchQuery() — 预取数据(页面切换变快)
- 4、Queries / Mutations 事件与生命周期 API
- (1)、onSuccess / onError / onSettled
- (2)、onMutate(乐观更新)
- 5、React Query Provider 核心 API
- (1)、QueryClientProvider — React Query 根提供器
- (2)、Hydration / dehydrate() — SSR/SSG 核心能力
- 6、开发工具相关 API
- (1)、ReactQueryDevtools
- 三、安装注册 react-query
- 四、使用 react-query
- 1、定义获取数据的查询函数 fetchTodos
- 2、使用 useQuery 获取服务器状态
- 3、新增数据(useMutation + 自动刷新列表)
- 4、删除数据(useMutation + 乐观更新)
- 5、组件组合
- 五、React Query 能做什么?不能做什么?
前言
React Query 是“旧名称”,只适用于 React。
从 v4 版本开始,React Query 团队把整个项目统一到 TanStack 品牌下,并命名为 TanStack Query。
TanStack Query 体系更加丰满了。不仅支持 React 的库了,而且还是跨框架的通用查询管理系统。比如:vue-query、svelte-query、solid-query等。
React Query 是一个用于管理服务端状态的强大 React 库,它的核心作用是让获取、缓存、同步和更新服务器数据变得简单高效。
一、TanStack Query(React Queryv4+)
React Query = TanStack Query for React(React 专用版本)
TanStack Query 是整个家族,React Query 是 TanStack Query 家族一员——在 React 上的实现——React Query 现在正式名为@tanstack/react-query。
React Query 从 v4 版本开始采用 “新体系”,并更名为 TanStack Query。
TanStack Query 不再仅支持 React 的库,而是跨框架的通用查询管理系统:
| 框架 | 对应的包 |
|---|---|
| React | @tanstack/react-query |
| Vue | @tanstack/vue-query |
| Svelte | @tanstack/svelte-query |
| Solid | @tanstack/solid-query |
| Angular(实验) | @tanstack/angular-query |
TanStack (品牌/生态)
├── TanStack Query (核心库)
│ ├── @tanstack/react-query ← React Query(React版本)
│ ├── @tanstack/vue-query
│ ├── @tanstack/svelte-query
│ └── @tanstack/solid-query
│
├── TanStack Table
├── TanStack Router
└── TanStack Virtual
1、从 React Query 到 TanStack Query 之间的变化
| 变化 | 优点 | 注意点 / 差异 |
|---|---|---|
@tanstack/react-query包名 | 更正规、模块化、框架无关 | 迁移时需要改 import |
网络模式 (networkMode) | 支持离线 + 在线策略 | 需要调整默认的行为 |
| 服务端缓存清理 | 减少内存泄漏 / 挂起问题 | SSR 项目需注意 cacheTime 默认值 |
| Promise 取消方式改动 | 使用标准AbortController更现代 | 旧代码需要重构取消逻辑 |
| 日志 API 改变 | 更灵活、更现代 | 旧日志方案不再可用 |
| 跟踪查询 (tracked) | 减少无意义渲染,提高性能 | 影响使用notifyOnChangeProps的旧代码 |
setQueryData更新逻辑增强 | 优化乐观更新逻辑 | 值为undefined时行为变化 |
| Mutation 缓存 GC | 减少内存,不用手动管理 | 需要了解 mutation 缓存机制 |
| React 18 支持 | 并发特性、同步订阅更好 | 升级 React 时更推荐 v4+ |
| 持久化机制完善 | 支持 localStorage / 异步持久化 | 迁移时需看接口兼容性 |
| 通知事件简化 | 订阅机制更清晰、统一 | 自定义订阅代码需调整 |
| TS 升级需求 | 类型更现代、对 ESM 支持强 | 旧 TS 版本可能不兼容 |
下面我们单从@tanstack/react-query入手,系统的学习下 TanStack Query 在 React 中的运用。
二、react-query 的核心 API
React Query 的核心 API 大致分为 3 大类:查询(Query)、修改(Mutation)、客户端缓存控制(QueryClient)。
1、查询核心 API(获取服务器状态)
(1)、useQuery() — React Query 的灵魂 API
用于获取服务器数据(GET 请求)。
功能:
- 自动缓存
- 自动重新请求
- 自动错误处理
- 自动状态(loading, error, success)
- 自动垃圾回收
示例:
const{data,isLoading,error}=useQuery({queryKey:['todos'],queryFn:fetchTodos,});这是 React Query 使用频率最高的 API。
(2)、useInfiniteQuery() — 无限加载 / 下拉加载更多
用于 分页加载、无限滚动 结构。
示例:
constinfinite=useInfiniteQuery({queryKey:['posts'],queryFn:fetchPosts,getNextPageParam:(lastPage)=>lastPage.nextCursor,});(3)、useSuspenseQuery() — 和 React Suspense 结合(新趋势)
示例:
const{data}=useSuspenseQuery({queryKey:['user',id],queryFn:getUser,});当你未来结合 React 19 / SSR / streaming,很实用。
2、Mutation 核心 API(提交数据、写入服务器)
(1)、useMutation() — 提交数据、写操作(POST/PUT/DELETE)
用于所有 非 GET 请求。
示例:
constmutation=useMutation({mutationFn:(newTodo)=>createTodo(newTodo),});包含的状态:
- isPending
- isSuccess
- isError
(2)、useSuspenseMutation() — Suspense 的 mutation 版本
很少用,但和 Suspense 架构一致。
3、Query Client(全局控制器)API
React Query 所有操作都依赖 QueryClient。
你在项目启动时创建它:
constqueryClient=newQueryClient();并注入 React 环境:
<QueryClientProviderclient={queryClient}>(1)、queryClient.fetchQuery() — 手动触发查询(常用于 SSR)
服务器渲染或预取数据非常强大:
await queryClient.fetchQuery({queryKey:['posts'],queryFn:fetchPosts,});(2)、queryClient.invalidateQueries() — 主动重刷缓存(非常关键)
Mutation 后最常用的动作:
queryClient.invalidateQueries({queryKey:['todos']});场景:
- 新增 todo → 刷新列表
- 更新用户信息 → 刷新关联页面
(3)、queryClient.refetchQueries() — 主动重新获取(立即刷新)
不同于 invalidate(标记为过期),refetch 立即执行。
queryClient.refetchQueries({queryKey:['todos'],});(4)、queryClient.setQueryData() — 手动更新缓存(无网络)
用于 乐观更新 或 自定义缓存更新。
queryClient.setQueryData(['todos'],old=>[...old,newTodo]);(5)、queryClient.getQueryData() — 读取缓存(不会触发请求)
constdata=queryClient.getQueryData(['todos']);(6)、queryClient.prefetchQuery() — 预取数据(页面切换变快)
用在“鼠标悬浮预加载页面”的场景:
queryClient.prefetchQuery({queryKey:['profile'],queryFn:fetchProfile,});React Router + React Query = 超流畅导航。
4、Queries / Mutations 事件与生命周期 API
(1)、onSuccess / onError / onSettled
常用于 mutation:
useMutation({mutationFn:updateUser,onSuccess:()=>queryClient.invalidateQueries(['user'])})(2)、onMutate(乐观更新)
支持 乐观 UI 更新:
onMutate:async(newTodo)=>{await queryClient.cancelQueries(['todos']);constprevious=queryClient.getQueryData(['todos']);queryClient.setQueryData(['todos'],old=>[...old,newTodo]);return{previous};}5、React Query Provider 核心 API
(1)、QueryClientProvider — React Query 根提供器
所有 Query/Mutation 的前提:
<QueryClientProviderclient={queryClient}>(2)、Hydration / dehydrate() — SSR/SSG 核心能力
Next.js、Remix 和 React 19 SSR 都需要 hydration API:
dehydrate(queryClient)6、开发工具相关 API
(1)、ReactQueryDevtools
超级强大,可实时查看缓存:
<ReactQueryDevtoolsinitialIsOpen={false}/>三、安装注册 react-query
首先要安装 @tanstack/react-query:
npminstall@tanstack/react-query然后在入口文件中必须加 QueryClientProvider:
// main.tsx / index.tsximport{QueryClient,QueryClientProvider}from'@tanstack/react-query';importAppfrom'./App';constqueryClient=newQueryClient();exportdefaultfunctionRoot(){return(<QueryClientProvider client={queryClient}><App/></QueryClientProvider>);}四、使用 react-query
使用的 React Query 管理“服务器状态”的步骤:
- 获取数据(useQuery)
- 创建数据(useMutation)
- 更新与删除
- 缓存、重新请求、乐观更新
- 实战项目文件结构
【举个例子】:
假设有一个服务器 API /api/todos。现在需要你实现以下需求:
①、获取 Todo 列表
②、新增 Todo
③、删除 Todo
④、自动刷新、缓存、错误处理
1、定义获取数据的查询函数 fetchTodos
// api/todoApi.tsexportconstfetchTodos=async()=>{constres=awaitfetch('/api/todos');if(!res.ok)thrownewError('Failed to fetch todos');returnres.json();};exportconstaddTodo=async(title:string)=>{constres=awaitfetch('/api/todos',{method:'POST',body:JSON.stringify({title}),headers:{'Content-Type':'application/json'}});if(!res.ok)thrownewError('Failed to add todo');returnres.json();};exportconstdeleteTodo=async(id:number)=>{constres=awaitfetch(`/api/todos/${id}`,{method:'DELETE'});if(!res.ok)thrownewError('Failed to delete todo');returnres.json();};2、使用 useQuery 获取服务器状态
import{useQuery}from'@tanstack/react-query';import{fetchTodos}from'./api/todoApi';exportfunctionTodoList(){const{data,isLoading,error}=useQuery({queryKey:['todos'],// 缓存 key(全局唯一)queryFn:fetchTodos,// 请求函数staleTime:5000,// 5 秒内不重新请求refetchOnWindowFocus:false,// 切回窗口不重新请求});if(isLoading)return<div>加载中...</div>;if(error)return<div>加载失败</div>;return(<ul>{data.map(todo=>(<li key={todo.id}>{todo.title}</li>))}</ul>);}3、新增数据(useMutation + 自动刷新列表)
import{useMutation,useQueryClient}from'@tanstack/react-query';import{addTodo}from'./api/todoApi';exportfunctionAddTodo(){constqueryClient=useQueryClient();constmutation=useMutation({mutationFn:(title:string)=>addTodo(title),onSuccess(){// 手动刷新 todos 列表queryClient.invalidateQueries(['todos']);},});consthandleAdd=()=>{mutation.mutate('新的任务');};return(<button onClick={handleAdd}disabled={mutation.isPending}>{mutation.isPending?'添加中...':'添加 TODO'}</button>);}4、删除数据(useMutation + 乐观更新)
React Query 的强大之处是:可以不用等服务器响应,先更新 UI,失败再回滚:
import{useMutation,useQueryClient}from'@tanstack/react-query';import{deleteTodo}from'./api/todoApi';exportfunctionDeleteTodoButton({id}){constqueryClient=useQueryClient();constmutation=useMutation({mutationFn:()=>deleteTodo(id),// 乐观更新onMutate:async()=>{await queryClient.cancelQueries(['todos']);constpreviousTodos=queryClient.getQueryData(['todos']);queryClient.setQueryData(['todos'],(old:any[])=>old.filter(todo=>todo.id!==id));return{previousTodos};},// 失败时回滚onError:(_err,_variables,context)=>{queryClient.setQueryData(['todos'],context.previousTodos);},// 成功后真正拉取最新数据onSettled:()=>{queryClient.invalidateQueries(['todos']);},});return(<button onClick={()=>mutation.mutate()}>删除</button>);}5、组件组合
exportdefaultfunctionApp(){return(<div><h1>Todo 管理(React Query)</h1><AddTodo/><TodoList/></div>);}五、React Query 能做什么?不能做什么?
负责管理“服务器状态”的难点:
- 缓存
- 后台刷新
- 自动请求合并
- 乐观更新
- 错误恢复
- 对象引用稳定性
- 重新请求策略
- 全局状态同步
不处理:
- 本地 UI 状态(modal 是否打开?)
- 表单状态
- 跨组件 UI 状态
这些 React Query 不能处理的,可以适当选用
useState/useReducer/Zustand之一来处理。