React Query 入门指南从 useQuery 到 useMutation 的完整数据获取实战【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本篇技术指南以 React Query现为 TanStack Query为主线系统讲解如何在 React 应用中通过useQuery读取数据、用useMutation执行创建/更新/删除操作并进阶掌握分页、无限滚动、依赖查询等技巧同时结合 Refine 框架对 React Query 钩子的扩展实现useUpdate、useList帮助你理解通用数据请求库 → 数据密集型应用框架的演进路径。读完本文你将能够独立完成一个具备缓存、错误处理与后台同步能力的 React 数据层。为什么需要 React Query从服务端状态管理的痛点说起在 Web 开发中从服务器加载数据、处理错误、保持客户端与服务端同步历来是一道复杂的难题。如果再加上弱网环境带来的不确定性任何开发者都会感到头疼每个组件都要手写 loading 状态、错误捕获、数据刷新逻辑代码很快变得冗长且难以维护。React Query 正是为化解这些痛点而生的解决方案——它专注于服务端状态server state的缓存与管理。无论是刚入门的新手还是希望提升数据获取能力的老手React Query 都能为你打下坚实的数据层基础。与传统的useEffectuseState手动管理方案相比React Query 的核心优势体现在三个方面内置查询缓存Query Caching数据一旦获取即可存入缓存后续复用而无需重复发起 API 请求自动状态管理查询的 loading / error / success 状态由库内部自动维护开发者无需编写繁琐的状态机逻辑内置错误处理对 API 错误的优雅处理开箱即用并支持全局重试与错误通知。前置条件与环境准备在开始之前请确保满足以下条件熟悉 JavaScript 语法具备 React.js 框架的基础知识理解 APIHTTP 请求的基本概念本地已安装 React Query 与 Axios。本文以 Jsonplaceholder 作为 API 端点用 React Query 与 Axios 完成服务端数据的获取与处理。在 React 项目中执行以下命令完成安装npm install react-query axios说明如果你从零开始一个新项目建议直接使用tanstack/react-queryv5 的包名这也是当前仓库 packages/core/package.json 中实际使用的版本tanstack/react-query: ^5.81.5。本文其余示例仍沿用原文档的react-query包名两者的 API 核心用法一致。应用入口配置 QueryClientProviderReact Query 的全局配置中心是QueryClient。在index.js中创建客户端实例并通过QueryClientProvider注入到整个应用import React from react; import ReactDOM from react-dom; import { QueryClient, QueryClientProvider } from react-query; import ./index.css; import App from ./App; const queryClient new QueryClient(); ReactDOM.render( QueryClientProvider client{queryClient} App / /QueryClientProvider, document.getElementById(root), );至此你的应用已经具备了 React Query 的完整能力所有在组件树中发起的查询与变更都会共享同一个QueryClient的缓存实例与全局配置。什么是 React Query一次查询与缓存的类比理解 React Query不妨借用搜索引擎的工作原理。当我们向 Google 发起查询时它从庞大的数据库中检索并返回最相关的信息React Query 则向 API 端点发起请求、获取数据——两者都在做查询query这件事。更进一步Google 会缓存网页以降低展示延迟React Query 同样会把 API 响应缓存在本地减少后续重复请求。这正是Query之名的由来这个库的职责就是让数据查询这件事变得轻而易举。在数据管理层面查询数据Querying Data指的是使用查询语言从数据库或数据集中请求特定信息的过程而 React Query 把这一过程封装为可声明式调用的钩子让开发者专注于想要什么数据而非如何获取、如何缓存、如何更新。用 useQuery 执行基础数据获取useQuery是 React Query 处理服务端状态的**读取Read**核心钩子。它接收一个查询键query key和一个查询函数query function返回包含查询状态loading / error / success、返回数据以及重新获取函数等信息的对象。下面通过一个示例从 Jsonplaceholder 获取文章标题列表import React from react; import { useQuery } from react-query; import axios from axios; const retrievePosts async () { const response await axios.get( https://jsonplaceholder.typicode.com/posts, ); return response.data; }; const DisplayPosts () { const { data: posts, error, isLoading, } useQuery(postsData, retrievePosts); if (isLoading) return divFetching posts.../div; if (error) return divAn error occurred: {error.message}/div; return ( ul {posts.map((post) ( li key{post.id}{post.title}/li ))} /ul ); }; export default DisplayPosts;这段代码展示了 React Query 的声明式威力retrievePosts负责用 Axios 发起请求并返回数据useQuery自动管理isLoading与error状态组件只需根据状态分支渲染即可。缓存机制在这里悄然生效当你以postsData作为查询键调用useQuery时React Query 完成请求后会把结果存入缓存并以该键作为缓存标识。如果后续再次以相同键调用useQuery而缓存仍有效它将直接返回缓存数据而非重新发起请求。用 useMutation 执行数据变更增 / 改 / 删如果说useQuery负责读那么useMutation则负责写Write操作——创建、更新与删除数据。它让 React Query 得以覆盖完整的 CRUD 闭环。需要注意Jsonplaceholder 是一个模拟 API并不会真正持久化创建、更新或删除的数据但它会返回成功或错误响应足以验证操作是否按预期执行。Create创建数据创建一个CreatePost组件import React, { useState } from react; import { useMutation } from react-query; import axios from axios; const CreatePost () { const [title, setTitle] useState(); const [body, setBody] useState(); const mutation useMutation((newPost) axios.post(https://jsonplaceholder.typicode.com/posts, newPost), ); const submitData () { mutation.mutate({ title, body }); }; if (mutation.isLoading) { return spanSubmitting.../span; } if (mutation.isError) { return spanError: {mutation.error.message}/span; } if (mutation.isSuccess) { return spanPost submitted!/span; } return ( div input typetext value{title} onChange{(e) setTitle(e.target.value)} placeholderTitle / input typetext value{body} onChange{(e) setBody(e.target.value)} placeholderBody / button onClick{submitData}Submit/button /div ); }; export default CreatePost;传入useMutation的函数即变更函数mutation function。调用mutation.mutate({ title, body })时变更正式执行并可通过mutation.isLoading、mutation.isError、mutation.isSuccess三个状态观察执行结果——与useQuery的状态管理模式一脉相承。Update更新数据更新与创建几乎同构只需将变更函数改为axios.put并在 URL 中带上要更新的资源 IDimport React, { useState } from react; import { useMutation } from react-query; import axios from axios; const UpdatePost () { const [title, setTitle] useState(); const [body, setBody] useState(); const mutation useMutation((updatedPost) axios.put(https://jsonplaceholder.typicode.com/posts/1, updatedPost), ); const submitData () { mutation.mutate({ title, body }); }; if (mutation.isLoading) { return spanUpdating.../span; } if (mutation.isError) { return spanError: {mutation.error.message}/span; } if (mutation.isSuccess) { return spanPost updated!/span; } return ( div input typetext value{title} onChange{(e) setTitle(e.target.value)} placeholderTitle / input typetext value{body} onChange{(e) setBody(e.target.value)} placeholderBody / button onClick{submitData}Update/button /div ); }; export default UpdatePost;相比 Create 版本这里仅做了两处改动axios.post换成axios.putPUT 请求URL 补充了目标 ID/posts/1。其余状态管理与渲染逻辑完全复用——这正是useMutation抽象的价值所在。Delete删除数据删除操作甚至无需表单一个按钮即可完成import React from react; import { useMutation } from react-query; import axios from axios; const DeletePost () { const mutation useMutation(() axios.delete(https://jsonplaceholder.typicode.com/posts/1), ); const deleteData () { mutation.mutate(); }; if (mutation.isLoading) { return spanDeleting.../span; } if (mutation.isError) { return spanError: {mutation.error.message}/span; } if (mutation.isSuccess) { return spanPost deleted!/span; } return ( div button onClick{deleteData}Delete Post/button /div ); }; export default DeletePost;将变更函数改为axios.delete并指定目标 ID 即可。通过上述三个示例可以看到useMutation以一致的模式统一了所有写操作极大简化了数据变更的开发负担。React Query 与框架Refine 如何扩展它的钩子React 生态中的框架可以基于 React Query 构建更高层的抽象。以 Refine 为例它在tanstack/react-query之上扩展了核心钩子增加了适合数据密集型应用的特性与定制选项——最典型的代表就是useUpdate与useList。useUpdateuseMutation 的扩展实现useUpdate是 React QueryuseMutation的扩展版本专门用于更新记录。从源码可以清楚看到它的实现基石——packages/core/src/hooks/data/useUpdate.ts 直接导入了 TanStack Query 的useMutation与useQueryClientimport { type UseMutationOptions, type MutateOptions, useMutation, useQueryClient, } from tanstack/react-query;其文档注释也明确写道useUpdateis a modified version ofreact-querysuseMutationfor update mutations. It usesupdatemethod as mutation function from thedataProviderwhich is passed toRefine.也就是说useUpdate将dataProvider中的update方法作为变更函数并在其外层叠加了 Refine 的资源解析、通知、乐观更新optimisticUpdateMap支持 list / many / detail 三类缓存的前置更新、undoable 撤销模式、数据失效invalidates等能力。在核心useMutation调用中mutationFn会根据参数校验缺失id、values或resource会抛出对应错误并最终委托给dataProvider(...).update({ resource, id, variables, meta })。useListuseQuery 的扩展实现useList则是 React QueryuseQuery的扩展版本用于按排序sorters、筛选filters、分页pagination等条件从resource获取数据。源码 packages/core/src/hooks/data/useList.ts 同样基于useQuery构建import { type QueryObserverResult, type UseQueryOptions, useQuery, } from tanstack/react-query;从实现细节看useList会通过handlePaginationParams规范化分页参数区分服务端分页mode: server与客户端分页mode: client此时在前端对全量数据做slice切片还会通过useResourceSubscription接入实时订阅live能力使列表在数据变更时自动刷新。这些都是在裸useQuery之上叠加的框架级增强。两个钩子的完整行为均有对应的单元测试验证例如 packages/core/src/hooks/data/useUpdate.spec.tsx 与 packages/core/src/hooks/data/useList.spec.tsx更详细的用法说明可参考仓库文档 use-update 数据钩子 与 use-list 数据钩子。小结如果你正在寻找一个充分发挥 React Query 能力的框架Refine 是很好的选择——它把数据查询与服务端状态管理的复杂性进一步封装让你可以用更少的代码构建完整的数据层。进阶React Query 高级查询技巧以下技巧覆盖分页、无限滚动、依赖查询、并行查询与后台同步帮助你应对更复杂的真实场景。分页查询Pagination将页码纳入查询键React Query 会为每一页独立缓存仅在新页码请求时发起网络调用配合keepPreviousData选项加载新页时可以保留上一页数据避免列表闪烁const fetchPosts async (page 1) { const response await axios.get(/api/posts?page${page}); return response.data; }; const { data, isLoading, isError } useQuery( [posts, page], () fetchPosts(page), { keepPreviousData: true, }, );无限滚动Infinite ScrolluseInfiniteQuery专为滚动到底部加载更多设计非常适合社交信息流或长列表。getNextPageParam决定何时触发下一次获取const fetchPosts async ({ pageParam 1 }) { const response await axios.get(/api/posts?page${pageParam}); return response.data; }; const { data, fetchNextPage, hasNextPage } useInfiniteQuery( posts, fetchPosts, { getNextPageParam: (lastPage, allPages) lastPage.nextPage ?? false, }, ); useEffect(() { if (hasNextPage) { fetchNextPage(); } }, [fetchNextPage, hasNextPage]);依赖查询Dependent Queries当一个查询需要依赖另一个查询的结果时使用enabled配置项控制执行时机。下面的例子先获取用户信息待拿到user.id后才发起该作者的文章查询const { data: user, isLoading: isUserLoading } useQuery(user, fetchUser); const { data: posts, isLoading: isPostsLoading } useQuery( [posts, user?.id], () fetchPosts(user.id), { enabled: !!user?.id, }, );并行查询Parallel Queries对于彼此独立、需要同时发起的数据集只需并列声明多个useQuery即可React Query 会自动并行执行并分别管理各自的加载与错误状态const { data: posts, isLoading: isPostsLoading } useQuery( posts, fetchPosts, ); const { data: comments, isLoading: isCommentsLoading } useQuery( comments, fetchComments, );后台数据同步Background Data SynchronizationReact Query 会在后台自动重新获取数据并更新 UI让用户始终看到最新内容。针对切回窗口时需要刷新的场景可开启refetchOnWindowFocus保证数据在用户重新聚焦页面时保持新鲜这对强调数据一致性的应用尤为关键const { data, isLoading } useQuery(posts, fetchPosts, { refetchOnWindowFocus: true, });从 React Query 到 TanStack Query v5有哪些变化自本文最初发布以来React Query 已演进为TanStack Query v5。数据获取、缓存、服务端状态同步这些核心能力保持不变但 v5 引入了一系列精化改进更一致的 APIqueryKey与queryFn的用法更加清晰统一全新设计的 DevTools为开发者提供更直观的查询与变更可视化面板显著增强的 TypeScript 支持强类型应用的开发体验大幅提升精细化的缓存管理减少了后台重新获取数据时的意外行为。如果你今天启动新项目建议直接使用 v5——学习曲线相同但开发体验更流畅且面向未来更具可持续性。仓库中的 Refine 核心包也已全面迁移至tanstack/react-queryv5见 packages/core/package.json其数据钩子均基于 v5 的useQuery/useMutation构建。结语在这篇入门指南中我们系统梳理了 React Query 的核心概念用useQuery声明式获取并缓存数据用useMutation统一执行增删改操作并通过分页、无限滚动、依赖查询、并行查询与后台同步等技巧应对复杂场景。像 Refine 这样的框架在 React Query 之上进一步扩展为数据密集型应用提供了开箱即用的完整解决方案。掌握 React Query你就能为自己的 React 项目构建出高效、可靠且体验流畅的数据层。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考