使用 react-query 进行更清晰的数据获取

2025-05-27

使用 react-query 进行更清晰的数据获取

我认为数据获取在 React 世界中不如状态管理那么重要和引人注目。人们经常将客户端状态和服务器状态组合到他们的状态管理解决方案中。我所说的服务器状态是指来自后端服务器的数据。例如,在 Redux 设置中,客户端状态和来自服务器的数据存储在存储中,更新通过 Action 和 Reducer 处理。客户端状态的变化通常会导致服务器状态的变化,因此在大多数情况下将它们组合起来是合理的。但我认为它们是两个独立的实体,如果处理得当,在某些情况下我们甚至可以摆脱客户端状态管理解决方案。

我开始寻找分离客户端和服务器状态管理的解决方案。我从 Angular 的背景转入 React 世界,想要一些简单的方案,比如将服务器数据存储在服务中,然后将其注入到组件中,这样就万事大吉了。在 React 中,如果多个组件都需要你获取的数据,你就必须维护一个全局状态管理方案。

react-query 来帮忙

然后,我研究了执行数据获取和维护服务器状态的库。我偶然发现了React-Query,然后就一鸣惊人!它满足了我的所有需求,甚至更多。它提供了一种维护服务器状态全局上下文的方法,并且以极低的配置提供了一个出色的缓存解决方案。此外,swr也同样出色。

例子

好了,闲话少叙。我们开始写代码吧。我通常这样设置我的 React 项目。我有一个文件夹叫做 ,pages里面存放了所有顶级路由。components一个文件夹存放了所有 UI 组件。还有一个文件夹叫做api,里面存放了所有服务器端 API。

假设我们有一个产品实体。该产品实体包含所有 CRUD 操作。因此,产品实体中需要包含以下 API 调用

1. Fetch all products
2. Fetch a specific product
3. Add a new product
4. Edit a product
5. Delete a product
Enter fullscreen mode Exit fullscreen mode

react-query为我们提供了一个useQuery可用于所有查询的钩子。这应该涵盖了上面列表中的第 1 点和第 2 点。
我们将通过包装 来为产品创建自己的数据获取钩子useQuery

我们的产品文件api/product.js看起来像这样
图像

让我们回顾一下如何使用来设置数据获取函数react-query

获取产品

我们先从获取产品开始。基本的实现useQuery看起来 没什么特别的。我们传入一个唯一的 ID作为第一个参数,并传入一个 fetch 函数来实际进行 API 调用。
图像
keyuseQuery

如果我们想在组件中使用它,我们可以这样做
图像

它为我们提供了加载和错误状态,我认为这很棒

我们已经完成了数据获取的设置,但功能远不止于此。任何列表页面都会有其他功能,例如search、等等filterspagination而 React-Query 让添加这些功能变得非常简单。让我们开始设置吧。

分页

在我们的Products组件中,我们可以将pagelimit值作为状态。page表示当前页码,limit表示页面上要显示的产品数量。

图像

下一步是将它与我​​们的useFetchProducts钩子连接起来。让我们useFetchProductspagelimit作为参数。

图像

让我们来分析一下这里发生了什么。这个useFetchProducts钩子现在接受pagelimit作为参数。它还将这两个参数添加到key,并将它们添加到获取 URL 中。

太棒了!就是这样。我们现在实现了分页功能。现在,每当组件中的page和 的值发生变化时,react-query 都会自动触发 API 请求并更新 UI。limitProducts

搜索

另一个重要的通用功能是搜索。因此,让我们name在产品字段中添加一个搜索功能。你可能已经猜到了,这与分页过程完全相同。我们将name在状态中添加一个字段,并将此状态值传递给我们的useFetchProducts钩子。

图像

我们的useFetchProducts意愿看起来是这样的。

图像

类似地,我们可以将任意数量的过滤/搜索参数挂载到我们的useFetchProducts钩子上。此钩子可以跨多个组件使用,无需任何全局状态管理系统。

缓存

缓存无疑是我最喜欢的 React-Query 功能。只需极少的代码,我们就能搭建一个强大的缓存系统。以我们的产品示例为例,假设我们希望产品缓存 10 秒。我们可以通过添加选项来实现staleTime 这样,每当使用相同的和调用此钩子时,都会使用缓存中的数据
图像
pagelimitname

这里需要重点理解的是key选项。它key唯一地标识一个请求。因此,值为 1 的请求page与值为 2 的请求是不一样的。page只有当三个键值都相同时,才会使用缓存中的值。

更新内部缓存

react-query还允许我们访问其内部缓存。我们可以随时更新此缓存。这意味着,我们可以设置单个产品的内部缓存值。

想象一下,我们获取了产品列表并将其显示在屏幕上。用户点击某个产品,我们会将其带到产品页面。在产品页面中,我们必须获取产品的详细信息并显示出来。但是!产品的详细信息已经在 React-query 的内部缓存中了。如果我们可以使用缓存而不是 API 调用呢?

让我们从创建一个useFetchProduct用于获取单个产品的钩子开始。
图像

这里没什么特别的。和我们之前做的差不多,只是它接收id一个参数。
这里要注意的是['product', id]它的键。我们将一个产品的键关联到id它的键上。

现在到了有趣的部分,每当我们获取产品列表时,我们都会使用每个单独产品的值设置内部缓存。react-query公开一个useQueryClient为我们提供内部缓存的钩子。

图像

每当我们的产品列表成功获取时,onSuccess就会调用 API 响应的函数。我们循环遍历每个产品,并使用该setQueryData方法将其存储在缓存中。

现在,每当用户从产品列表页面移动到单个产品页面时,都会使用缓存中的值,而不是进行 API 调用。

结论

所以,我发现 React-Query 是一款极其简单且强大的数据获取解决方案。使用 React-Query 后,我甚至从一些项目中移除了全局状态管理解决方案。快去他们的代码库里表达一下我的喜爱吧!

干杯!

文章来源:https://dev.to/siddharthvenkatesh/cleaner-data-fetching-with-react-query-4klg
PREV
我的 GitHub 个人资料如何让我在 Spotify 找到工作
NEXT
.toLocaleString,最被低估的 JavaScript 功能之一