📡利用以下方式执行useQuery
现在从 React 执行我们的 TRACKS
查询。为此,我们将使用 Apollo 客户端的 useQuery
hook 在 src/pages/tracks.js
中。
The useQuery
hook 是一个主要 API,用于在 React 应用中执行查询。我们在 React 组件中运行 查询,方法是调用 useQuery
并将我们的 GraphQL 查询字符串传递给它。这样就能轻松地从 React 组件运行查询。
当我们组件渲染时, useQuery
从 阿波罗客户端返回一个对象,其中包含 loading
、 error
和 data
属性,我们可以使用这些属性来渲染我们的 UI。让我们将所有这些放入代码中。
注意:查看 关于 useQuery
hook 的官方 Apollo 文档了解有关此函数的更多信息。
首先,我们需要从 @apollo/client
包中导入 useQuery
(我们已经导入 gql
):
import { useQuery, gql } from "@apollo/client";
现在,在我们的 Tracks
函数组件中(在打开的花括号之后),我们从 useQuery
hook 声明三个解构常量: 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}`;
如果没有 ,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
钩子,并解构结果中的 loading
、error
和 data
属性。
让我们重启应用程序。我们首先看到加载消息,然后看到原始 JSON 响应。响应中包含 tracksForHome
对象(操作 的名称),其中包含 Track
对象数组。到目前为止看起来不错!现在,让我们在实际视图中使用此数据。
呈现 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
属性并使用它的 title
、thumbnail
、author
、length
和 modulesCount
。因此,我们只需将每个 TrackCard
传递一个 Track
对象,该对象来自我们的 query 响应。
让我们回到 src/pages/tracks.js
。我们已经看到,服务器对我们的 TRACKS
GraphQL query 的响应包括一个 tracksForHome
键,其中包含音轨数组。
为每个音轨创建一个卡片,我们将映射 tracksForHome
数组并返回一个 TrackCard
组件,其对应的音轨数据作为其属性:
<Layout grid>{data?.tracksForHome?.map((track) => (<TrackCard key={track.id} track={track} />))}</Layout>
我们刷新浏览器,瞧!我们得到了一堆带有酷炫猫咪宇航员缩略图的漂亮卡片。我们的音轨标题、长度、模块数和作者信息都得益于我们的 TrackCard
组件而完美地显示。很酷吧!
**注意:**您可能会在浏览器控制台中看到一个警告,内容类似于 "发现了两个具有相同键 track_01
的子元素。" 因为我们仍在模拟我们的音轨数据,所以每个音轨都有相同的 id
,但是 React 希望每个 key
是唯一的。在我们将服务器更新为使用真实音轨数据(在 Lift-off II 中)后,此警告将消失,因此我们现在可以放心地忽略它。
封装查询结果
在刷新浏览器时,您可能已经注意到,因为我们将 loading
消息作为一个简单的字符串返回,所以我们 不 当前不显示组件的整个布局和导航栏(error
消息也是如此)。我们应该确保我们的 UI 行为在 query 的所有阶段中保持一致。
实现这一点使用了我们的 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
组件将取而代之处理这些状态。
在 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 {idtitlethumbnaillengthmodulesCountauthor {namephoto}}}`;/*** 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 应用的第一个特性! 🚀
为了构建我们的主页网格特性,我们采用模式优先方法,这意味着我们在开始编写任何代码前就已经从客户端的角度考虑了数据需求。
我们定义了架构,并使用 Apollo 服务器来构建基本 GraphQL端点,该端点提供模拟响应。
然后,我们使用 Apollo Sandbox浏览器在本地 GraphQL 服务器上以交互方式构建和测试查询。
最后,我们开发了 Catstronauts 应用程序的客户端。我们使用了 React、 Apollo 客户端和 useQuery
挂钩来我们的 GraphQL 服务器上执行 查询,并将我们的曲目显示在一个漂亮的网格卡片布局中。
在接下来的教程中,我们将使用 REST 数据源将我们的应用程序连接到实时数据,并编写我们的第一个 解析器,以便将数据提供给客户端。
在 下一篇任务“升空 II'中见!
在此分享你对此次课程的问题及评论
你的反馈有助于我们提升!如果你遇到困难或感到困惑,请告诉我们,我们会帮助你。所有评论都是公开的,并且必须遵循 Apollo 行为准则。请注意,已解决或已处理的评论可能会被删除。
你需要一个 GitHub 帐户才能在下面发帖。还没有账户? 转而发帖到我们的 Odyssey 论坛。