📡 使用以下方法执行useQuery
现在执行我们的 TRACKS 查询 从 React 中!为此,我们将使用 Apollo Client 的 useQuery 钩子在 src/pages/tracks.js 中。
这 useQuery 钩子是在 React 应用程序中执行查询的主要 API。我们通过调用 查询 在 React 组件中运行 查询,并将我们的 GraphQL 查询 字符串作为参数传递给它。这使得从 React 组件运行查询变得轻而易举。
当我们的组件渲染时,useQuery 返回一个来自 Apollo Client 的对象,其中包含 loading、error 和 data 属性,我们可以使用这些属性来渲染我们的 UI。让我们将所有这些内容放入代码中。
首先,我们需要从 @apollo/client 包中导入 useQuery(我们已经导入了 gql):
import { useQuery, gql } from "@apollo/client";
现在,在我们的 Tracks 函数式组件中(在打开的花括号下方),我们将从我们的 useQuery 钩子中声明三个解构常量:loading、error 和 data。我们使用 TRACKS 查询 作为参数调用 useQuery:
const { loading, error, data } = useQuery(TRACKS);
在下面,我们将首先使用 loading 常量:
if (loading) return "Loading...";
只要 loading 为 true(表示 查询 仍在进行中),该组件将只渲染一个 Loading... 消息。
当 loading 为 false 时,查询 就完成了。这意味着我们要么拥有 data,要么拥有 error。
让我们添加另一个条件语句来处理 error 状态:
if (error) return `Error! ${error.message}`;
如果我们没有错误,我们一定有数据!现在,我们将使用 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>;};
使用 useQuery 钩子和 SPACECATS 查询,从结果中解构 loading、error 和 data 属性。
让我们重启我们的应用程序。我们首先看到加载消息,然后是一个原始的 JSON 响应。该响应包含一个 tracksForHome 对象(我们 操作 的名称),它包含一个 Track 对象数组。到目前为止看起来不错!现在,让我们在实际视图中使用这些数据。

渲染 TrackCards
方便的是,我们已经有一个 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 属性,并使用它的 title、thumbnail、author、length 和 modulesCount。因此,我们只需要为每个 TrackCard 传递一个来自我们 查询 响应的 Track 对象。
让我们回到 src/pages/tracks.js。我们已经看到,我们的 TRACKS GraphQL 查询 的服务器响应包含一个 tracksForHome 键,它包含轨道的数组。
要为每个轨道创建一个卡片,我们将遍历 tracksForHome 数组,并返回一个 TrackCard 组件,其对应轨道的属性作为其属性:
<Layout grid>{data?.tracksForHome?.map((track) => (<TrackCard key={track.id} track={track} />))}</Layout>
我们刷新浏览器,瞧!我们得到了一堆漂亮的外观,带有酷炫的猫宇航员缩略图。我们的轨道标题、长度、模块数量和作者信息都漂亮地显示了出来,这要归功于我们的 TrackCard 组件。真棒!

注意: 你可能会在浏览器控制台中看到一条警告,类似于,"遇到两个具有相同键的子节点,track_01。" 这是因为我们仍然在模拟我们的轨道数据,所以每个轨道都具有相同的 id,但 React 希望每个 key 都是唯一的。当我们更新服务器以使用真实轨道数据(在发射 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";
我们现在可以删除此文件中处理 loading 和 error 状态的行,因为 QueryResult 组件将处理它们。
我们把 QueryResult 包裹在我们的 map 函数周围,并赋予它需要的 props:
<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 } from "../components";/** TRACKS gql query to retrieve all tracks */const TRACKS = gql`query GetTracks {tracksForHome {idtitlethumbnaillengthmodulesCountauthor {idnamephoto}}}`;/*** 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) => (<TrackCard key={track.id} track={track} />))}</QueryResult></Layout>);};export default Tracks;
就这样!我们的主页上填充了酷炫的轨道卡片网格,就像我们在最初的原型中设计的那样。
🏆 课程完成!
恭喜你完成了我们 Catstronauts 应用程序的第一个功能!🚀
为了构建我们的主页网格功能,我们采用了模式优先方法,这意味着我们在开始编写代码之前就从客户端的角度考虑了数据需求。
我们定义了我们的模式,并使用 Apollo Server 构建了一个基本的 GraphQL 端点,提供模拟响应。
然后,我们使用 Apollo Sandbox Explorer 以交互方式构建和测试针对本地 GraphQL 服务器 的查询。
最后,我们开发了 Catstronauts 应用程序的客户端。我们使用了 React、Apollo Client 以及 useQuery 钩子来执行针对 GraphQL 服务器 的 查询,并在漂亮的网格卡片布局中显示我们的轨道。
在接下来的课程中,我们将使用 REST 数据源 将我们的应用程序连接到实时数据,并编写我们的第一个 解析器,以便将这些数据提供给客户端。
在 下一个任务,升空 II 中见!
分享您对本课的疑问和评论
您的反馈有助于我们改进!如果您遇到困难或困惑,请告诉我们,我们会帮助您。所有评论都是公开的,必须遵循 Apollo 行为准则。请注意,已解决或处理的评论可能会被删除。
您需要一个 GitHub 帐户才能在下面发帖。没有? 改在我们的 Odyssey 论坛上发帖。