8. 带有变量的 useQuery 钩子
4m

概述

是时候处理 UI,让我们的曲目详情页面动起来了。

在此课程中,我们将

  • 创建track页面
  • 将新 GET_TRACK 导入到前端
  • 调用 useQuery钩子,传递一个 trackId

访问曲目页面

我们的应用已通过路由逻辑设置,可以显示特定曲目的页面。我们来尝试一下。

运行 npm start

这应在浏览器中打开到 http://127.0.0.1:3000/localhost:3000以显示主页。

然后,我们导航到: localhost:3000/track/c_0。我们仍应看到一个空 Catstronauts 布局,但这告诉我们该路由正在工作。我们将开始用从 中检索到的数据来填充它。

Screenshot showing a blank layout on the /track/c_0 page
任务!

📄 建设曲目页面

让我们给这个曲目页面一些东西来显示!

跳转到 src/pages文件夹,并打开 track.tsx

此文件输出名为 Track 的基本组件,但目前仅有很少的功能。

import React from "react";
import { Layout, QueryResult } from "../components";
const Track = () => {
return <Layout></Layout>;
};
export default Track;

处理导入

让我们导入一些用于构建此页面的软件包。

首先,我们将从 __generated__ 文件夹导入 gql,然后从 @apollo/client 导入 useQuery。接下来,为了确定 显示其详细信息的磁道,我们需要访问路由中传递的 trackId。为此,我们使用 useParams,它来自 react-router-dom

src/pages/track.tsx
import { gql } from "../__generated__";
import { useQuery } from "@apollo/client";
import { useParams } from "react-router-dom";

现在,让我们跳到 Track 组件中。在花括号内,我们将对通过 useParams 函数返回的对象解构出 trackId。如果没有传递任何 trackId,我们将其设置为一个空字符串。

const Track = () => {
const { trackId = "" } = useParams();
return <Layout></Layout>;
};

💻 设置我们客户端的查询

是时候构建我们的磁道 了。我们将使用全大写字母称其为 GET_TRACK 并使用 __generated__ 文件夹中的 gql 函数。

src/pages/track.tsx
export const GET_TRACK = gql(`
# our query goes here
`);

现在,我们可以手动构建我们的 ,也可以从 Sandbox 中获取已经完成的查询,在 操作 面板中复制查询,然后将其粘贴在 gql 标签中的反引号之间,即 GET_TRACK

query GetTrack($trackId: ID!) {
track(id: $trackId) {
id
title
author {
id
name
photo
}
thumbnail
length
modulesCount
description
numberOfViews
modules {
id
title
length
content
videoUrl
}
}
}

重新运行代码生成

我们已为前端编写新的 ,为了保持 TypeScript 代码准确,我们需要在根文件夹再次运行代码生成命令!此操作将重新评估前端代码中使用的操作,并自动生成保持代码一致且无 bug 所需的类型。每当我们更新 GraphQL 操作或添加或删除操作时,我们都应确保重新生成我们的类型!

npm run generate

我们应看到一些关于我们的代码生成运行成功的输出,然后我们就可以继续进行!

🪝 设置 useQuery hook

正如您从以前的课程中所知,我们使用 Apollo 客户端的 hook 从我们的客户端向 发出调用。

我们将在此 Track 组件中使用此 hook。在 return 行之前,我们可以声明我们从 useQuery hook 接收到的通常的 loadingerrordata 对象。

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

我们传递 GET_TRACK 作为 hook 的第一个 ,现在与我们之前的查询相比最大的区别是添加了第二个参数: options 对象。

此对象将持有 variables 键,注 variables,带 “S” 因为它可以有多个 。此 variables 键将对象作为值,我们将在其中传递我们的 trackId

const { loading, error, data } = useQuery(GET_TRACK, {
variables: { trackId },
});

QueryResult 组件

与主页类似,我们将使用预先构建的 QueryResult 组件来处理任何错误并正确显示加载状态。

Layout 组件的打开和关闭标签内添加 QueryResult 组件:

<Layout>
<QueryResult error={error} loading={loading} data={data}>
{/* this is where our component displaying the data will go */}
</QueryResult>
</Layout>

加载完成且没有错误时, QueryResult 组件将呈现其子项,将它们所需的数据传递给它们。

TrackDetail 组件

我们提供了便捷的 TrackDetail 组件,随时可以使用来显示该数据。它位于 src/components 文件夹中,所以如果你有兴趣,可以随时花一分钟查看它,了解 UI 元素如何组织的。

让我们在 track.tsx 文件的顶部导入 TrackDetail 组件。

import TrackDetail from "../components/track-detail";

现在在 QueryResult 内部,我们可以渲染 TrackDetail 组件并设置 track 属性为 data?.track,这里使用可选链,因为数据在 加载完成之前不可用。

<TrackDetail track={data?.track} />

我们已经为轨道页准备好了!下面是经过我们所有更改之后 track.tsx 文件的应有样子:

src/pages/track.tsx
import React from "react";
import { gql } from "../__generated__";
import { useQuery } from "@apollo/client";
import { Layout, QueryResult } from "../components";
import { useParams } from "react-router-dom";
import TrackDetail from "../components/track-detail";
export const GET_TRACK = gql(`
query GetTrack($trackId: ID!) {
track(id: $trackId) {
id
title
author {
id
name
photo
}
thumbnail
length
modulesCount
numberOfViews
modules {
id
title
length
}
description
}
}
`);
const Track = () => {
const { trackId = "" } = useParams();
const { loading, error, data } = useQuery(GET_TRACK, {
variables: { trackId },
});
return (
<Layout>
<QueryResult error={error} loading={loading} data={data}>
<TrackDetail track={data?.track} />
</QueryResult>
</Layout>
);
};
export default Track;

💻 检查浏览器!

如果我们导航回浏览器到 localhost:3000/track/c_0,我们应该看到该轨道页以及显示的所有详细信息!我们可以看到我们太空小猫的精美大缩略图、标题、轨道详细信息、作者、模块详细信息和描述!如果我们更改 URL 以显示不同的轨道 ID,例如 c_1c_2,该页面会更新为正确的数据。

太棒了,我们走上了正确的 轨道🥁

Screenshot showing a track page with all of its details

让我们通过 localhost:3000 跳回至主页。

我们仍然在轨道卡片网格上显示了主页,因此我们当时并未破坏任何内容。现在,如果我们单击卡片,我们将转到该轨道的页面。

太棒了!我们可以返回主页,单击其他一些轨道,并查看其数据是否也可以正确加载。

😲 缓存后台

现在,你可能会注意到,如果我们单击以前已单击过的轨道,则该页面会极速弹出!与单击我们之前从未单击过的轨道相比,我们可以在页面上看到任何详细信息之前看到加载图标在旋转。

这种快速加载行为要归功于

第一次向 发送 时, 会将结果存储在缓存中。下次我们尝试发送相同的查询时(例如,再次导航到同一页面),它将从缓存加载结果,而不是通过网络发送不必要的调用。

非常方便! 在我们为之前的一节课中设置的 InMemoryCache 中处理这种缓存行为。

练习

从客户端查询
我们用
 
 函数包装查询字符串,然后使用
 
 钩子将其发送到我们的服务器。

将此框中的项目拖到上面的空白处

  • graphql

  • useQuery

  • useState

  • gql

  • useApolloClient

你能从主页导航到正确的轨道页面吗?在“Cat-strophysics, master class”轨道上的最后一个模块是什么?
代码挑战!

使用 useQuery 钩子将 GET_SPACECAT 查询发送至服务器。它将 spaceCatId 作为变量。从钩子的返回对象中解构 loadingerrordata 属性。

加载...
加载进度
useQuery 钩子
useQuery 钩子返回一个对象,其中包含我们应用中使用的三个有用的属性: 
 
 指示查询是否已完成以及是否已返回结果。 
 
 是一个对象,包含操作抛出的任何错误。
 
 在查询完成之后包含查询结果。要设置 
 
 在我们的查询中,我们在 中声明它们
 
useQuery 钩子的参数,在一个选项对象内部。

将此框中的项目拖到上面的空白处

  • isComplete

  • data

  • error

  • first

  • loading

  • variables

  • arguments

  • second

  • results

主要结论

  • useQuery 钩子接收一个可选的第二个 ,一个 options 对象,在其中我们可以定义 variables 对象。
  • 结果存储在它的缓存中,这允许更快速的内容加载。

接下来

我们的应用设置到目前为止 查询 数据,但如何更改数据呢?为了为我们的应用程序带来一些交互性,我们将深入了解此课程的最终主题:

上一个

分享您对此课程的问题和评论

本课程目前处于

测试版
.你的反馈有助于我们提升产品!如果你遇到困难或困惑,请联系我们,我们会帮助你解决。所有评论都是公开的,并且必须遵循 Apollo的行为准则。请注意,评论如果已经解决或回复,有可能被删除。

你需要使用 GitHub 账户才能在下面发帖。还没有 GitHub 账户? 在我们的 Odyssey 论坛发帖。