10. useQuery hook
5m
您当前使用的课程是旧版本。 查看课程变更日志.

📡利用以下方式执行useQuery

现在从 React 执行我们的 TRACKS 。为此,我们将使用 useQuery hook 在 src/pages/tracks.js 中。

The useQuery hook 是一个主要 API,用于在 React 应用中执行查询。我们在 React 组件中运行 ,方法是调用 useQuery 并将我们的 字符串传递给它。这样就能轻松地从 React 组件运行查询。

当我们组件渲染时, useQuery返回一个对象,其中包含 loadingerrordata属性,我们可以使用这些属性来渲染我们的 UI。让我们将所有这些放入代码中。

注意:查看 关于 useQuery hook 的官方 Apollo 文档了解有关此函数的更多信息。

首先,我们需要从 @apollo/client包中导入 useQuery(我们已经导入 gql):

import { useQuery, gql } from "@apollo/client";

现在,在我们的 Tracks函数组件中(在打开的花括号之后),我们从 useQueryhook 声明三个解构常量: loadingerrordata。我们用我们的 TRACKS 作为其 调用 useQuery

const { loading, error, data } = useQuery(TRACKS);

在其下方,我们首先使用 loading常量:

if (loading) return "Loading...";

只要 loadingtrue(指示 仍处于飞行中),组件将只呈现 Loading... 消息。

loading 为 false 时, 已完成。这意味着我们要么有 data,要么有 error

让我们添加另一个条件语句来处理 error 状态:

if (error) return `Error! ${error.message}`;

如果没有 ,error,我们肯定有 data!目前,我们只需要使用 JSON.stringify 将我们的原始数据对象转储出来,看看会发生什么。

<Layout grid>{JSON.stringify(data)}</Layout>

添加完所有内容后,已完成的 Tracks 组件如下所示。请确保你的代码与之匹配!

const Tracks = () => {
const { loading, error, data } = useQuery(TRACKS);
if (loading) return "Loading...";
if (error) return `Error! ${error.message}`;
return <Layout grid>{JSON.stringify(data)}</Layout>;
};
代码挑战!

SPACECATS 查询使用 useQuery 钩子,并解构结果中的 loadingerrordata 属性。

让我们重启应用程序。我们首先看到加载消息,然后看到原始 JSON 响应。响应中包含 tracksForHome 对象( 的名称),其中包含 Track 对象数组。到目前为止看起来不错!现在,让我们在实际视图中使用此数据。

https://127.0.0.1:3000
The JSON response to our query, outputted directly into the UI

呈现 TrackCard

很方便的是,我们已经有一个 TrackCard 组件已准备就绪。我们需要导入组件并将响应数据输入其中:

import TrackCard from "../containers/track-card";

让我们打开 /src/containers/track-card.js 来查看它如何工作。

/**
* Track Card component renders basic info in a card format
* for each track populating the tracks grid homepage.
*/
const TrackCard = ({ track }) => {
const { title, thumbnail, author, length, modulesCount } = track;
//...
};

该组件使用 track 属性并使用它的 titlethumbnailauthorlengthmodulesCount。因此,我们只需将每个 TrackCard 传递一个 Track 对象,该对象来自我们的 响应。

让我们回到 src/pages/tracks.js。我们已经看到,服务器对我们的 TRACKS 的响应包括一个 tracksForHome 键,其中包含音轨数组。

为每个音轨创建一个卡片,我们将映射 tracksForHome 数组并返回一个 TrackCard 组件,其对应的音轨数据作为其属性:

<Layout grid>
{data?.tracksForHome?.map((track) => (
<TrackCard key={track.id} track={track} />
))}
</Layout>

我们刷新浏览器,瞧!我们得到了一堆带有酷炫猫咪宇航员缩略图的漂亮卡片。我们的音轨标题、长度、模块数和作者信息都得益于我们的 TrackCard 组件而完美地显示。很酷吧!

https://127.0.0.1:3000
The UI of our Catstronauts app, displaying a number of track cards

**注意:**您可能会在浏览器控制台中看到一个警告,内容类似于 "发现了两个具有相同键 track_01 的子元素。" 因为我们仍在模拟我们的音轨数据,所以每个音轨都有相同的 id,但是 React 希望每个 key 是唯一的。在我们将服务器更新为使用真实音轨数据(在 Lift-off II 中)后,此警告将消失,因此我们现在可以放心地忽略它。

封装查询结果

在刷新浏览器时,您可能已经注意到,因为我们将 loading 消息作为一个简单的字符串返回,所以我们 当前不显示组件的整个布局和导航栏(error 消息也是如此)。我们应该确保我们的 UI 行为在 的所有阶段中保持一致。

实现这一点使用了我们的 QueryResult 助手组件。这不是 Apollo 库直接提供的组件。我们已将其添加到应用中,以在我们的应用中以一致、可预测的方式结果。

打开 components/query-result。此组件使用 useQuery 挂钩的返回值作为属性值。然后执行基本条件逻辑以渲染一个旋转器、一条错误消息及其子项:

const QueryResult = ({ loading, error, data, children }) => {
if (error) {
return <p>ERROR: {error.message}</p>;
}
if (loading) {
return (
<SpinnerContainer>
<LoadingSpinner data-testid="spinner" size="large" theme="grayscale" />
</SpinnerContainer>
);
}
if (!data) {
return <p>Nothing to show...</p>;
}
if (data) {
return children;
}
};

回到我们的 tracks.js 文件,我们在顶部导入 QueryResult

import QueryResult from "../components/query-result";

现在我们可以移除此文件中处理 loadingerror 状态的行,因为 QueryResult 组件将取而代之处理这些状态。

map 函数周围包装 QueryResult 并向其提供它需要的属性值:

<QueryResult error={error} loading={loading} data={data}>
{data?.tracksForHome?.map((track) => (
<TrackCard key={track.id} track={track} />
))}
</QueryResult>

刷新浏览器,我们会在加载时看到一个精美的旋转器,然后我们卡片出现了!

useQuery 挂钩有什么用?

经过所有这些代码处理之后, tracks.js 文件应该如下所示:

import React from "react";
import { useQuery, gql } from "@apollo/client";
import TrackCard from "../containers/track-card";
import { Layout, QueryResult } from "../components";
/** TRACKS gql query to retrieve all tracks */
const TRACKS = gql`
query GetTracks {
tracksForHome {
id
title
thumbnail
length
modulesCount
author {
name
photo
}
}
}
`;
/**
* Tracks Page is the Catstronauts home page.
* We display a grid of tracks fetched with useQuery with the TRACKS query
*/
const Tracks = () => {
const { loading, error, data } = useQuery(TRACKS);
return (
<Layout grid>
<QueryResult error={error} loading={loading} data={data}>
{data?.tracksForHome?.map((track, index) => (
<TrackCard key={track.id} track={track} />
))}
</QueryResult>
</Layout>
);
};
export default Tracks;

好了!我们的主页已充满酷炫的航迹卡片网格,正如我们的初始模拟中所述。

任务!

🏆 课程完成!

恭喜完成我们的 Catstronauts 应用的第一个特性! 🚀

为了构建我们的主页网格特性,我们采用模式优先方法,这意味着我们在开始编写任何代码前就已经从客户端的角度考虑了数据需求。

我们定义了架构,并使用 来构建基本 端点,该端点提供模拟响应。

然后,我们使用 浏览器在本地 上以交互方式构建和测试查询。

最后,我们开发了 Catstronauts 应用程序的客户端。我们使用了 React、 useQuery挂钩来我们的 上执行 ,并将我们的曲目显示在一个漂亮的网格卡片布局中。

在接下来的教程中,我们将使用 REST 将我们的应用程序连接到实时数据,并编写我们的第一个 ,以便将数据提供给客户端。

上一个

在此分享你对此次课程的问题及评论

你的反馈有助于我们提升!如果你遇到困难或感到困惑,请告诉我们,我们会帮助你。所有评论都是公开的,并且必须遵循 Apollo 行为准则。请注意,已解决或已处理的评论可能会被删除。

你需要一个 GitHub 帐户才能在下面发帖。还没有账户? 转而发帖到我们的 Odyssey 论坛。