尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
TanStack React Query 实战指南:在 React 中优雅地获取、缓存与更新异步数据
TanStack React Query 实战指南在 React 中优雅地获取、缓存与更新异步数据【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/queryReact Query现归属于 TanStack Query 家族在本仓库中的定位是Hooks for fetching, caching and updating asynchronous data in React——一套面向 React 的异步数据获取、缓存与更新 Hooks。它以tanstack/react-query包形式存在于 packages/react-query 目录其核心逻辑沉淀在底层 packages/query-core 中并共享给 Solid Query、Svelte Query、Vue Query、Angular Query 等适配层。读完本文你将掌握 React Query 的三大核心概念查询、变更、失效刷新理解其开箱即用的缓存默认值与底层 Observer 实现原理并能直接照搬可运行的完整示例到自己的 React 项目中。React Query 解决了什么问题大多数 Web 框架并不会为服务端状态提供一套统一的数据获取方案。开发者通常被迫把组件状态与副作用拼凑在一起或使用通用状态管理库去存放异步数据——而这两者都不是为服务端状态设计的。服务端状态与客户端状态有本质差异它远程持久化、需要异步 API 读写、被多方共享可能随时被他人修改、且容易在应用中过期。TanStack Query 正是为攻克这些问题而生缓存与去重、后台刷新过期数据、判断数据何时过期、分页与懒加载优化、服务端状态的内存管理与垃圾回收、以及基于结构共享structural sharing的结果记忆化。更关键的是这一切开箱即用、零配置并可在应用成长过程中按需定制。从 docs/framework/react/overview.md 可以确认它能帮助开发者删除大量复杂易错的数据代码让应用更快更省带宽。快速上手三大核心概念文档 docs/framework/react/quick-start.md 用一段代码浓缩了 React Query 的全部核心Queries查询、Mutations变更与Query Invalidation失效刷新。下面是官方 Quick Start 的完整可运行示例import { useQuery, useMutation, useQueryClient, QueryClient, QueryClientProvider, } from tanstack/react-query import { getTodos, postTodo } from ../my-api // 创建客户端 const queryClient new QueryClient() function App() { return ( // 将客户端提供给整个应用 QueryClientProvider client{queryClient} Todos / /QueryClientProvider ) } function Todos() { // 访问客户端 const queryClient useQueryClient() // 查询 const query useQuery({ queryKey: [todos], queryFn: getTodos }) // 变更 const mutation useMutation({ mutationFn: postTodo, onSuccess: () { // 失效并重新拉取 queryClient.invalidateQueries({ queryKey: [todos] }) }, }) return ( div ul {query.data?.map((todo) ( li key{todo.id}{todo.title}/li ))} /ul button onClick{() { mutation.mutate({ id: Date.now(), title: Do Laundry, }) }} Add Todo /button /div ) } render(App /, document.getElementById(root))这三行调用构成了 React Query 的日常使用闭环useQuery拉取并缓存数据useMutation提交写操作onSuccess回调里通过queryClient.invalidateQueries让相关查询失效、触发自动重新拉取。创建并挂载 QueryClient从 QueryClientProvider.tsx 源码可以看到 Provider 的职责并不只是注入上下文它通过React.createContext创建QueryClientContextuseQueryClient从中读取客户端实例若既没有传入参数、组件树上也没有 Provider会抛出No QueryClient set, use QueryClientProvider to set one的错误挂载/卸载时会调用client.mount()/client.unmount()这会订阅窗口焦点focus与在线online事件——这正是窗口重新聚焦自动刷新断线重连自动恢复能力的来源。export const QueryClientProvider ({ client, children }) { React.useEffect(() { client.mount() return () { client.unmount() } }, [client]) return ( QueryClientContext.Provider value{client} {children} /QueryClientContext.Provider ) }在 React 19 环境下tanstack/react-query的 peerDependencies 为react: ^18 || ^19见 package.json运行时只依赖tanstack/query-core一个包。Queries声明式依赖唯一键的异步数据文档 docs/framework/react/guides/queries.md 定义了查询的本质一个查询是对异步数据源的声明式依赖且与一个唯一键unique key绑定。订阅一个查询至少需要两样东西一个唯一的 queryKey——它内部用于缓存、共享与重新拉取一个返回 Promise 的queryFn——resolve 出数据或抛出错误。import { useQuery } from tanstack/react-query function App() { const info useQuery({ queryKey: [todos], queryFn: fetchTodoList }) }如果方法会修改服务器数据文档明确建议改用 Mutations 而不是 Query。status 与 fetchStatus两套状态机useQuery返回的 result 对象包含两套正交的状态status——数据状态回答我们有没有数据isPending/status pending查询还没有数据isError/status error查询遇到错误可通过error属性读取isSuccess/status success查询成功数据在data属性中。fetchStatus——拉取状态回答queryFn 是否在运行fetching正在拉取paused想拉取但被暂停如离线详见网络模式idle当前没有动作。为什么需要两套状态因为后台重拉与 stale-while-revalidate 逻辑让两者的组合几乎都可能出现success fetching表示成功数据展示中、后台正在刷新pending paused表示没有数据且当前离线。另外isFetching在包括后台重拉在内的任何拉取时刻都为true。TypeScript 会在你先检查pending与error后自动收窄data的类型。标准的渲染模板对绝大多数查询先判isPending、再判isError、最后假定数据可用即可function Todos() { const { isPending, isError, data, error } useQuery({ queryKey: [todos], queryFn: fetchTodoList, }) if (isPending) return spanLoading.../span if (isError) return spanError: {error.message}/span return ( ul {data.map((todo) ( li key{todo.id}{todo.title}/li ))} /ul ) }若偏好字符串状态可改用if (status pending)/if (status error)的写法二者等价。源码视角useQuery 的底层实现从 useQuery.ts 可以看到useQuery本身是一层薄封装真正的工作交给useBaseQuery与QueryObserverexport function useQuery(options: UseQueryOptions, queryClient?: QueryClient) { return useBaseQuery(options, QueryObserver, queryClient) }QueryObserver来自tanstack/query-core源码位于 packages/query-core/src负责订阅 queryCache、计算派生状态并触发回调。文件顶部大量 JSDoc 示例揭示了useQuery的几种典型进阶用法均可直接参考initialData重载当设置了initialData返回类型被收窄为DefinedUseQueryResultdata永远不为undefined——即使重拉失败列表仍能连同错误一起展示源码示例见 useQuery.tsselect派生select: (posts) posts.length只改变组件拿到的数据形状缓存里存的仍是完整Post[]依赖查询与skipTokenqueryFn: postId ! null ? () fetchPost(postId) : skipToken可在类型安全的前提下禁用查询省去非空断言注意refetch在queryFn为skipToken时不生效需要手动触发请改用enabled: false分页占位数据placeholderData: keepPreviousData让翻页时保留上一页数据可见配合isPlaceholderData禁用按钮防止重复点击。queryOptions让查询配置可复用、类型可推断queryOptions.ts 提供的queryOptions()允许把同一份配置同时用于useQuery与命令式 API如queryClient.query。它有三种重载按是否设置initialData、queryFn是否为skipToken自动选择返回的 options 会携带带数据标签的 queryKey实现端到端类型推断import { queryOptions, useQuery } from tanstack/react-query // 参数化工厂同一份 options 可按 id 复用 export const postOptions (id: string) queryOptions({ queryKey: [post, id], queryFn: () fetchPost(id), }) function Post({ id }: { id: string }) { const { data, isPending, isError, error } useQuery(postOptions(id)) if (isPending) return Loading... if (isError) return spanError: {error.message}/span return h1{data.title}/h1 }注意initialData只在查询尚未创建或缓存时生效若以函数形式传入会在共享/根查询初始化期间被调用一次且必须同步返回数据。initialData会持久化进缓存且默认视为过期除非设置了staleTime。Mutations创建/更新/删除数据与副作用与查询不同变更Mutation用于创建、更新、删除数据或执行服务端副作用。文档 docs/framework/react/guides/mutations.md 给出了标准示例function App() { const mutation useMutation({ mutationFn: (newTodo) { return axios.post(/todos, newTodo) }, }) return ( div {mutation.isPending ? ( Adding todo... ) : ( {mutation.isError ? ( divAn error occurred: {mutation.error.message}/div ) : null} {mutation.isSuccess ? divTodo added!/div : null} button onClick{() { mutation.mutate({ id: new Date(), title: Do Laundry }) }} Create Todo /button / )} /div ) }Mutation 的状态机一个 mutation 同一时刻只能处于以下四种状态之一isIdle/status idle空闲或处于全新/重置状态isPending/status pending正在执行isError/status error遇到错误通过error读取isSuccess/status success执行成功通过data读取返回数据。通过mutate的单个变量或对象参数向mutationFn传值。值得注意的是mutate是异步函数在React 16 及更早版本中不能直接作为事件回调使用受事件池机制影响需要包一层函数再调用const onSubmit (event) { event.preventDefault() mutation.mutate(new FormData(event.target)) } return form onSubmit{onSubmit}.../form重置 Mutation 状态需要清除 mutation 的error或data时调用reset函数如用户切换了输入内容后清掉上一次的错误提示。变更的威力配合失效与乐观更新当useMutation与queryClient.invalidateQueries、queryClient.setQueryData组合使用时API 定义见 QueryClient.md它才是真正的杀手锏。源码 useMutation.ts 的 JSDoc 给出了完整的最佳实践成功后失效刷新最常见的组合const addMutation useMutation({ mutationFn: addTodo, onSuccess: () queryClient.invalidateQueries({ queryKey: [todos] }), })乐观更新 失败回滚const addMutation useMutation({ mutationFn: addTodo, onMutate: async (newTodo) { // 1. 取消进行中的查询避免与乐观更新竞争 await queryClient.cancelQueries({ queryKey: [todos] }) // 2. 快照旧数据 const previousTodos queryClient.getQueryDataArraystring([todos]) // 3. 立即用新数据更新缓存 queryClient.setQueryDataArraystring([todos], (old) [ ...(old ?? []), newTodo, ]) // 4. 返回快照供 onError 回滚 return { previousTodos } }, onError: (_err, _newTodo, onMutateResult) { queryClient.setQueryData([todos], onMutateResult?.previousTodos) }, onSettled: () { queryClient.invalidateQueries({ queryKey: [todos] }) }, })源码还强调两个细节一是调用mutate时可通过第二个参数传入单次调用级的onSuccess/onError/onSettled回调只对最近一次调用生效且仅当组件仍挂载时才会触发二是批量提交多个 mutation 时mutateAsync会为每次调用返回 Promise可用Promise.all等待全部完成或用Promise.allSettled逐条甄别失败的项。开箱即用的重要默认值文档 docs/framework/react/guides/important-defaults.md 列出了激进但合理的默认行为是排查为什么没重新拉取/为什么拉了这么多次的关键默认行为说明与调整方式缓存数据默认视为stale过期用staleTime全局或按查询调整设2 * 60 * 1000则 2 分钟内只读缓存不触发重拉除非手动失效设Infinity则永不因过期重拉但仍可被手动失效设static则连手动失效也无法刷新invalidateQueries对static无效refetchOnMount/refetchOnWindowFocus/refetchOnReconnect的always也会被阻止适合功能开关、登录权限等运行期不可变的数据过期查询在三种时机后台自动重拉新实例挂载、窗口重新聚焦、网络重新连接可分别用refetchOnMount、refetchOnWindowFocus、refetchOnReconnect定制refetchInterval定时轮询与staleTime相互独立见 Polling无活动实例的查询标记为 inactive 并保留默认5 分钟后垃圾回收可用gcTime调整默认1000 * 60 * 5毫秒失败的查询静默重试 3 次指数退避可用retry与retryDelay调整结果默认结构共享若数据未实际变化则保持引用不变利于useMemo/useCallback值稳定仅对 JSON 兼容值生效大响应可关闭structuralSharing或提供自定义比较函数结语从 packages/react-query/README.md 的功能清单看React Query 覆盖了传输层无关的数据获取REST、GraphQL、Promise 皆可、自动缓存与刷新stale-while-revalidate、窗口聚焦、轮询/实时、并行与依赖查询、多层级缓存与自动垃圾回收、分页与游标查询、无限滚动与滚动恢复、请求取消、React Suspense 与 fetch-as-you-render 预取以及专属 Devtools可在 examples/react 中找到对应示例工程。这套能力全部建立在一个核心抽象之上Observer 模式。无论是useQuery的 useBaseQuery.ts 还是useMutation的 useMutation.tsReact 层都只是用useSyncExternalStore订阅query-core中的 Observer 实例将核心缓存逻辑与任何 UI 框架解耦——这也是同一套query-core能同时驱动 react-query、vue-query、solid-query、svelte-query 与 angular-query-experimental 的根本原因。想深入框架无关的缓存、垃圾回收与重试算法请直接阅读 query-core 源码想对照真实项目写法examples/react 下的 auto-refetching、pagination、optimistic-updates、infinite-query-with-max-pages 等目录都是现成的参考工程。【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

HTTPS性能优化实战:TLS协议与加密套件调优

HTTPS性能优化实战:TLS协议与加密套件调优

1. HTTPS优化实战指南:从原理到性能提升作为一名经历过多次HTTPS性能调优的Web开发者,我深知一个配置不当的HTTPS连接可能让页面加载时间增加50%以上。本文将分享我在实际项目中验证过的HTTPS优化方案,涵盖协议配置、证书管理、会话复用等核心…

📅 2026/9/10 14:30:48
Cal.diy API v2 认证机制完全指南:API Key、OAuth 平台认证与错误处理实战

Cal.diy API v2 认证机制完全指南:API Key、OAuth 平台认证与错误处理实战

Cal.diy API v2 认证机制完全指南:API Key、OAuth 平台认证与错误处理实战 【免费下载链接】cal.diy Scheduling infrastructure for absolutely everyone. 项目地址: https://gitcode.com/GitHub_Trending/ca/cal.diy 本文面向需要在自研应用中对接 Cal.diy…

📅 2026/9/10 14:25:46
CVAT实战指南:3条部署路线+AI预标注,让数据标注效率提升10倍

CVAT实战指南:3条部署路线+AI预标注,让数据标注效率提升10倍

CVAT实战指南:3条部署路线AI预标注,让数据标注效率提升10倍 【免费下载链接】cvat Computer Vision Annotation Tool (CVAT) is a leading platform for building high-quality visual datasets for vision AI. It offers open-source, cloud, and enter…

📅 2026/9/10 14:25:46
MORE NEWS

更多资讯

📰

OmniRoute 部署实战:使用 flyctl 将自托管 AI 网关发布到 Fly.io 的完整指南

OmniRoute 部署实战:使用 flyctl 将自托管 AI 网关发布到 Fly.io 的完整指南 【免费下载链接】OmniRoute Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Work…

📰

GIS投影那些事:格陵兰「放了气」→ 联合国三天前刚投票,美国不同意

为什么同一颗地球,换一种画法,国家会“变大”或“变小”? 你可能在手机地图上无数次见过世界地图,却很少意识到一个问题: 屏幕上的地球,其实并不是地球。 地球接近球体,而电脑屏幕是一张平面…

📰

在 CopilotKit 中接入 Microsoft Agent Framework (Python):从 AG-UI 后端到智能频道的完整实战指南

在 CopilotKit 中接入 Microsoft Agent Framework (Python):从 AG-UI 后端到智能频道的完整实战指南 【免费下载链接】CopilotKit The Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol 项…

📰

基于C语言的铅笔姿态与笔迹检测装置设计与实现

简介:2024年陕西省大学生电子设计竞赛七校联赛C题完整源码,面向电子设计竞赛参赛者与嵌入式C语言进阶学习者。项目以铅笔姿态检测与笔迹识别为核心,包含完整工程文件、驱动代码与算法实现,并附有测评结果和过程记录。压缩包共297个…

📰

生成式 AI 初学者课程第 18 课:LLM 微调(Fine-Tuning)实战指南

生成式 AI 初学者课程第 18 课:LLM 微调(Fine-Tuning)实战指南 【免费下载链接】generative-ai-for-beginners 21 Lessons, Get Started Building with Generative AI 项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-fo…

📰

解决 tiny11builder 构建失败:“oscdimg.exe not found“ 完整排查与修复指南

解决 tiny11builder 构建失败:"oscdimg.exe not found" 完整排查与修复指南 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder 用 tiny11build…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬