☰
TanStack Query 的 React Query 解读
2026/10/18 23:55:45 网站建设 项目流程

目录

  • 前言
  • 一、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之一来处理。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询