如何将 React Query 与 React 和 GraphQL 结合使用

2025-06-10

如何将 React Query 与 React 和 GraphQL 结合使用

React Query是一个库,它提供了一组用于在 React 应用程序中获取、缓存和更新数据的钩子。在本教程中,我们将研究 React Query 并学习如何在 React 和 GraphQL 应用程序中使用它。

什么是 React Query?

React Query (RQ) 是一个面向 React 应用的高性能数据同步库。它提供了一系列用于获取和管理数据的钩子。它与后端无关,这意味着您可以使用 REST、GraphQL 或任何您喜欢的 API,RQ 对此不予置评。React Query 开箱即用,无需配置即可处理缓存、后台更新和过时数据。RQ 的缓存层功能强大,且配置工作量极小。

React Query 使状态管理变得简单,因为它允许您几乎毫不费力地获取、修改和缓存数据。并且还可以针对更高级的用例进行自定义。虽然 React Query 为您做了很多事情,但它并不能完全替代客户端状态管理库,因为 RQ 无法处理 UI 状态(用于控制应用程序交互部分的状态);它是一个用于获取和同步数据的库。

然而,RQ 旨在取代客户端状态下用于管理缓存数据的样板代码和相关连接,只需几行代码即可完成。RQ 必须管理服务器和客户端之间的异步操作,并使用 Redux、MobX、Zustand 甚至 React Context 来处理 UI 状态。这样,您将获得简化的应用程序逻辑,并以更少的代码为用户提供流畅的体验。

我们正在构建什么

在本指南中,我们将使用 React、React Query 和 GraphQL 构建一个博客应用。我们将从 TakeShape GraphQL API 中检索数据。让我们开始吧!

设置

在构建新的 React 应用之前,我们需要在TakeShape上注册一个账户(免费),然后创建一个新项目来获取 GraphQL API 来使用。创建账户并创建只读 API 密钥后,打开命令行界面并运行以下命令:

npx create-react-app rq-graphql-app
Enter fullscreen mode Exit fullscreen mode

此命令将为我们创建一个新的 React 应用。接下来,我们需要安装一些库。浏览到项目根目录并执行以下操作:

npm install react-query react-router-dom graphql graphql-request react-markdown
Enter fullscreen mode Exit fullscreen mode

以下是您要安装的每个库的作用:

  • react-query允许与 GraphQL API 交互并检索数据。
  • react-router-dom在我们的应用程序中启用路由。
  • graphql是 的依赖项graphql-request
  • graphql-request允许从 GraphQL 后端获取数据。
  • react-markdown帮助在 React 应用程序中渲染 Markdown。

安装依赖项后,我们就可以开始操作并查看 React Query 的实际运行情况。

文件夹结构

您的项目结构如下:

├── src
|  ├── components
|  |  ├── Header.js
|  |  ├── Layout.js
|  |  ├── Post.js
|  |  └── PostTemplate.js
|  ├── App.js
|  ├── useRequest.js
|  ├── index.css
|  ├── index.js
├── .env
├── package.json
└── yarn.lock
Enter fullscreen mode Exit fullscreen mode

请特别注意该useRequest.js文件。它是一个自定义钩子,使用 RQ 从 TakeShape GraphQL API 检索数据。这个文件是神奇之处;它帮助与 API 交互以获取博客文章。您也可以在组件中使用 RQ 钩子,但最好有一个自定义钩子,以避免重复操作。

接下来,让我们配置我们的应用程序以使用 React Query。

设置 React Query

// index.js
import React from "react";
import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "react-query";

import App from "./App";
import "./styles.css";

const queryClient = new QueryClient();

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </React.StrictMode>,
  rootElement
);
Enter fullscreen mode Exit fullscreen mode

为了使用 RQ 的钩子与我们的 GraphQl API 交互,我们需要使用 RQ 库查询提供程序包装我们的顶级应用程序组件。

使用 React Query

// useRequest.js
import { useQuery } from "react-query";
import { GraphQLClient, gql } from "graphql-request";

const API_URL = `https://api.takeshape.io/project/${process.env.PROJECT_ID}/v3/graphql`;

const graphQLClient = new GraphQLClient(API_URL, {
  headers: {
    Authorization: `Bearer ${process.env.API_KEY}`
  }
});

export function useGetPosts() {
  return useQuery("get-posts", async () => {
    const { getPostList } = await graphQLClient.request(gql`
      query {
        getPostList {
          items {
            _id
            title
            description
            content
          }
        }
      }
    `);
    return getPostList;
  });
}

export function useGetPost(postId) {
  return useQuery(["get-post", postId], async () => {
    const { getPost } = await graphQLClient.request(
      gql`
        query getPost($postId: ID!) {
          getPost(_id: $postId) {
            _id
            content
            description
            title
          }
        }
      `,
      { postId }
    );
    return getPost;
  });
}
Enter fullscreen mode Exit fullscreen mode

在 中useRequest.js,我们首先导入useQuery钩子和 graphl-request。接下来,我们API_URL使用 TakeShape 提供的凭证声明常量。对于每个请求,我们需要包含一个带有 TakeShape API 密钥的授权标头,以便向 GraphQL API 进行身份验证。使用GraphQLClient允许我们在每个请求上设置 API 密钥。

要从 API 获取所有博客文章,我们使用useGetPosts函数。该useQuery钩子需要一个键 ( get-posts) 和一个 GraphQL 查询。钩子可以接收更多选项,但在本例中,我们只需要这两个。获取完成后,我们将返回数据。React Query 会在返回值后附加一些数据,以便处理加载和错误状态。

接下来,useGetPost接收id要获取的帖子的 。为了将 传递id给 GraphQL 查询,我们需要将其作为第二个参数添加到request()方法中。这样,数据就会被获取并返回。

自定义钩子已准备就绪,可供使用。让我们创建 React 组件并依赖该钩子来检索数据。

创建组件

// components/Post.js
import React from "react";
import { Link } from "react-router-dom";
export default function Post({ article }) {
  const { _id, title, description } = article;
  return (
    <article className="Article">
      <h1>{title}</h1>
      <p>{description}</p>
      <Link to={`/single-post/${_id}`}>Read more &rarr;</Link>
    </article>
  );
}
Enter fullscreen mode Exit fullscreen mode

该组件负责显示博客文章预览。它接收对象作为参数,然后相应地显示它。

// components/PostTemplate.js
import React from "react";
import ReactMarkdown from "react-markdown";
import { useParams } from "react-router-dom";
import { useGetPost } from "../useRequest";
export default function PostTemplate() {
  const { id } = useParams();
  const { data, error, isLoading, isSuccess } = useGetPost(id);

  if (error) return <h1>Something went wrong!</h1>;
  if (isLoading) return <h1>Loading...</h1>;

  return (
    isSuccess && (
      <article className="Post">
        <h1>{data.title}</h1>
        <ReactMarkdown source={data.content} />
      </article>
    )
  );
}
Enter fullscreen mode Exit fullscreen mode

PostTemplate.js是一个用于显示博客文章的模板。id会从路由器参数中取出,然后传递给useGetPost钩子。这样,我们现在就可以使用它来获取文章了id。它会返回 RQ 提供的数据和一些状态,以便在出现问题时进行处理。

显示博客文章

// App.js
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";

import { useGetPosts } from "./useRequest";
import Post from "./components/Post";
import PostTemplate from "./components/PostTemplate";
import Layout from "./components/Layout";

export default function App() {
  const { data, error, isLoading, isSuccess } = useGetPosts();

  if (error) return <h1>Something went wrong!</h1>;
  if (isLoading) return <h1>Loading...</h1>;

  return (
    <Router>
      <Layout>
        <Route path="/" exact>
          {isSuccess &&
            data.items.map((post) => <Post key={post._id} article={post} />)}
        </Route>
        <Route path="/single-post/:id">
          <PostTemplate />
        </Route>
      </Layout>
    </Router>
  );
}
Enter fullscreen mode Exit fullscreen mode

在 中App.js,我们导入自定义钩子,并使用它从 API 获取所有博客文章。然后循环遍历响应数据,并使用Post组件显示这些文章。

现在我们可以在浏览器中测试示例应用了。在 CLI 中打开项目目录并运行:

npm start
Enter fullscreen mode Exit fullscreen mode

如果一切正常,应用程序将在这里启动并运行:[http://localhost:3000/](http://localhost:3000/)

https://paper-attachments.dropbox.com/s_646CBDE6B4B65BA76ED96FD5802A93352FA28BDA14D66C9EE4BBDB0C473A606D_1612187764273_blog-app-preview.PNG

应用预览

太棒了!我们的博客应用看起来棒极了。

React Query 自带专用的开发者工具。它可以帮助您直观地了解 React Query 的所有内部工作原理,并可能节省您数小时的调试时间。要启用它,我们需要在 中启用它index.js

// index.js
import React from "react";
import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";

import App from "./App";
import "./styles.css";

const queryClient = new QueryClient();

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  </React.StrictMode>,
  rootElement
);
Enter fullscreen mode Exit fullscreen mode

导入并添加为组件的子组件。就这样!开发者工具已经可以使用了。让我们在浏览器中试试看ReactQueryDevtoolsreact-queryQueryClientProvider

https://paper-attachments.dropbox.com/s_646CBDE6B4B65BA76ED96FD5802A93352FA28BDA14D66C9EE4BBDB0C473A606D_1612188533287_devtools.PNG

开发者工具

点击 React Query 的 logo 后,开发者工具就会弹出,展现其强大的功能。尽情使用吧!

您可以在CodeSandbox中找到完成的项目。感谢阅读!

结论

React Query 是一个用于管理服务器和客户端之间异步操作的实用库。它持续受到关注,并受到 Google、Facebook、Amazon 和 Microsoft 等大型公司在生产环境中的信赖。人们用它来简化状态管理,因为它拥有出色的缓存策略,可以同步和更新服务器状态,并且样板代码更少。对于下一个需要远程数据获取的项目来说,RQ 是一个不错的选择。

鏂囩珷鏉ユ簮锛�https://dev.to/takeshape/how-to-use-react-query-with-react-and-graphql-5go8
PREV
如何使用 React 和 TalkJS 构建类似 LinkedIn 的消息应用程序 - 第 2 部分
NEXT
TypeScript 中枚举没必要用?【讨论】枚举对编译后的 JavaScript 文件的影响 我的想法