2021 年 9 月 27 日

具有 TypeScript、PostgreSQL、Next.js、Prisma 和 GraphQL 的全端應用程式:GraphQL API

本文是一個課程的第二部分,您將在此課程中使用 Next.js、GraphQL、TypeScript、Prisma 和 PostgreSQL 建立一個全端應用程式。在本文中,您將建立 GraphQL API 並在前端與其互動。

Fullstack App With TypeScript, PostgreSQL, Next.js, Prisma & GraphQL: GraphQL API

目錄

簡介

在本課程中,您將學習如何建置 "awesome-links",這是一個全端應用程式,使用者可以在其中瀏覽精選連結列表並為他們最喜歡的連結加上書籤。

上一部分中,您使用 Prisma 設定資料庫層。在本部分的結尾,您將學習 GraphQL:它是什麼以及如何使用它在 Next.js 應用程式中建置 API。

開發環境

若要按照本教學課程進行操作,您需要安裝 Node.js 和 GraphQL 擴充功能。您還需要有一個正在執行的 PostgreSQL 執行個體。

注意:您可以在本機設定 PostgreSQL,或在 Heroku 上設定託管執行個體。請注意,在本課程結尾的部署步驟中,您將需要遠端資料庫。

複製儲存庫

您可以在 GitHub 上找到本課程的完整原始碼

注意:每篇文章都有對應的分支。這樣,您就可以在閱讀時跟著操作。透過查看 part-2 分支,您將擁有與本文相同的起點。

若要開始使用,請導覽至您選擇的目錄,並執行以下命令來複製儲存庫。

您現在可以導覽至複製的目錄,安裝相依性並啟動開發伺服器

應用程式將在 https://127.0.0.1:3000/ 上執行,您將看到四個項目。資料是硬式編碼的,來自 /data/links.ts 檔案。

What the starter project looks like

為資料庫植入種子資料

設定 PostgreSQL 資料庫後,將 env.example 檔案重新命名為 .env,並設定資料庫的連線字串。之後,執行以下命令以在資料庫中建立移轉和資料表

如果 prisma migrate dev 未觸發種子資料步驟,請執行以下命令來為資料庫植入種子資料

此命令將執行 seed.ts 指令碼,該指令碼位於 /prisma 目錄中。此指令碼使用 Prisma Client 將四個連結和一個使用者新增至您的資料庫。

專案結構和相依性概觀

您將看到以下資料夾結構

這是一個 Next.js 應用程式,其中設定了 TailwindCSS 以及 Prisma。

pages 目錄中,您將找到三個檔案

  • _app.tsx:全域 App 元件,用於新增在頁面變更之間持續存在的導覽列,以及新增全域 CSS。
  • about.tsx:此檔案匯出一個 React 元件,該元件會轉譯位於 https://127.0.0.1:3000/about 的頁面。
  • index.tsx:首頁,其中包含連結列表。這些連結已在 /data/links.ts 檔案中硬式編碼。

接下來,您將找到一個 prisma 目錄,其中包含以下檔案

  • schema.prisma:資料庫的結構描述,以 PSL (Prisma 結構描述語言) 撰寫。如果您想了解如何為此應用程式建立資料庫模型,請查看本課程的上一部分
  • seed.ts:將為資料庫植入種子資料指令碼與虛擬資料。

以傳統方式建置 API:REST

在本課程的上一部分中,您使用 Prisma 設定了資料庫層。下一步是在資料模型之上建置 API 層,這將讓您可以從用戶端請求或傳送資料。

建構 API 的常見方法是讓用戶端將請求傳送至不同的 URL 端點。伺服器將根據請求類型擷取或修改資源,並傳回回應。這種架構樣式稱為 REST,它具有一些優點

  • 彈性:一個端點可以處理不同類型的請求
  • 可快取:您需要做的就是快取特定端點的回應
  • 用戶端和伺服器之間的分隔:不同的平台 (例如,Web 應用程式、行動應用程式等) 可以取用 API。

REST API 及其缺點

雖然 REST API 具有優點,但它們也有一些缺點。我們將使用 awesome-links 作為範例。

以下是一種可能的結構化 awesome-links REST API 的方式

資源HTTP 方法路由描述
使用者GET/users傳回所有使用者及其資訊
使用者GET/users/:id傳回單一使用者
連結GET/links傳回所有連結
連結GETPUTDELETE/links/:id傳回單一連結、更新或刪除它。id 是連結的 id
使用者GET/favorites傳回使用者的書籤連結
使用者POST/link/save將連結新增至使用者的最愛
連結POST/link/new建立新連結 (由管理員完成)

每個 REST API 都不同

另一位開發人員可能會以不同的方式建構他們的 REST API,具體取決於他們認為合適的方式。這種彈性是有代價的:每個 API 都不同。

這表示每次您使用 REST API 時,您都需要瀏覽其文件並了解

  • 不同的端點及其 HTTP 方法。
  • 每個端點的請求參數。
  • 每個端點傳回的資料和狀態碼。

當第一次使用 API 時,這種學習曲線會增加摩擦並降低開發人員的生產力。

另一方面,建置 API 的後端開發人員需要管理它並維護其文件。

當應用程式的複雜性增加時,API 也會隨之增加:更多需求導致建立更多端點。

端點的增加很可能會引入兩個問題:過度提取提取不足資料。

過度提取和提取不足

當您提取超出您需要的資料時,就會發生過度提取。這會導致效能降低,因為您消耗了更多頻寬。

另一方面,有時您會發現端點未傳回 UI 中顯示所需的所有內容,因此您最終會向另一個端點發出一個或多個請求。這也會導致效能降低,因為將會發生瀑布式的網路請求。

在 "awesome-links" 應用程式中,如果您想要一個頁面來顯示所有使用者及其連結,您將需要對 /users/ 端點進行 API 呼叫,然後對 /favorites 發出另一個請求以提取他們的最愛。

/users 端點傳回使用者及其最愛並不能解決問題。那是因為您最終會得到一個龐大的 API 回應,這將需要很長時間才能載入。

REST API 未類型化

關於 REST API 的另一個缺點是它們未類型化。您不知道端點傳回的資料類型,也不知道要傳送的資料類型。這導致對 API 進行假設,這可能會導致錯誤或無法預測的行為。

例如,當發出請求時,您是以字串還是數字形式傳遞使用者 ID?哪些請求參數是選用的,哪些是必要的?這就是為什麼您會使用文件,但是,隨著 API 的發展,文件可能會過時。有些解決方案可以解決這些挑戰,但我們不會在本課程中涵蓋它們。

GraphQL,REST 的替代方案

GraphQL 是一種新的 API 標準,由 Facebook 開發並開放原始碼。它為 REST 提供了一種更有效率和彈性的替代方案,用戶端可以在其中接收完全所需的資料。

您只需將請求傳送到單一端點,而不是將請求傳送到一個或多個端點並拼接回應。

以下是一個 GraphQL 查詢範例,該查詢傳回 "awesome-links" 應用程式中的所有連結。您將在稍後建置 API 時定義此查詢

Example of GraphQL query

即使連結有更多欄位,API 也只傳回 idtitle

注意:這是 GraphiQL,一個用於執行 GraphQL 作業的遊樂場。它提供了我們將在稍後詳細介紹的優良功能

現在您將了解如何開始建置 GraphQL API。

定義結構描述

一切都從 GraphQL 結構描述開始,您可以在其中定義 API 可以執行的所有作業。您還可以指定作業的輸入引數以及回應類型。

此結構描述充當用戶端和伺服器之間的合約。它也可以作為開發人員取用 GraphQL API 的文件。您可以使用 GraphQL 的 SDL (結構描述定義語言) 定義結構描述。

讓我們看看如何為 "awesome-links" 應用程式定義 GraphQL 結構描述。

定義物件類型和欄位

您需要做的第一件事是定義物件類型。物件類型代表您可以從 API 提取的一種物件。

每個物件類型都可以有一個或多個欄位。由於您希望應用程式中有使用者,因此您需要定義 User 物件類型

User 類型具有以下欄位

  • id,類型為 ID
  • email,類型為 String
  • image,類型為 String
  • role,類型為 Role。這是一個列舉,這表示使用者的角色可以採用兩個值之一:USERADMIN
  • bookmarks,類型為 Link 的陣列。表示使用者可以有很多連結。接下來您將定義 Link 物件。

這是 Link 物件類型的定義

這是 LinkUser 物件類型之間的多對多關係,因為 Link 可以有很多使用者,而 User 可以有很多連結。這是在資料庫中使用 Prisma 建模的。

定義查詢

若要從 GrahQL API 提取資料,您需要定義 Query 物件類型。這是一種您可以在其中定義每個 GraphQL 查詢進入點的類型。對於每個進入點,您定義其引數及其傳回類型。

以下是一個傳回所有連結的查詢。

links 查詢傳回 Link 類型的陣列。! 用於指示此欄位不可為 null,這表示當查詢此欄位時,API 將始終傳回值。

您可以根據您想要建置的 API 類型新增更多查詢。對於 "awesome-links" 應用程式,您可以新增一個查詢以傳回單一連結、另一個查詢以傳回單一使用者,以及另一個查詢以傳回所有使用者。

  • link 查詢採用類型為 ID 的引數 id,並傳回 Linkid 引數是必要的,且回應不可為 null。
  • user 查詢採用類型為 ID 的引數 id,並傳回 Userid 引數是必要的,且回應不可為 null。
  • users 查詢傳回 User 類型的陣列。id 引數是必要的。回應不可為 null。

定義變異

若要建立、更新或刪除資料,您需要定義 Mutation 物件類型。慣例上,任何導致寫入的作業都應透過變異明確傳送。同樣地,您不應使用 GET 請求來修改資料。

對於 "awesome-links" 應用程式,您將需要不同的變異來建立、更新和刪除連結

  • createLink 變異採用 categorydescriptiontitleurlimageUrl 作為引數。所有這些欄位的類型都是 String 且為必要項。此變異傳回 Link 物件類型。
  • deleteLink 變異採用類型為 IDid 作為必要引數。它會傳回必要的 Link
  • updateLink 變異採用與 createLink 變異相同的引數。但是,引數是選用的。這樣一來,當更新 Link 時,您將只傳遞您想要更新的欄位。此變異傳回必要的 Link

定義查詢和變異的實作

到目前為止,您只定義了 GraphQL API 的結構描述,但您尚未指定當查詢或變異執行時應該發生什麼事。負責執行查詢或變異實作的功能稱為解析器。在解析器內部,您可以將查詢傳送至資料庫或將請求傳送至協力廠商 API。

在本教學課程中,您將在解析器內部使用 Prisma,以將查詢傳送至 PostgreSQL 資料庫。

建置 GraphQL API

若要建置 GraphQL API,您將需要一個 GraphQL 伺服器,該伺服器將提供單一端點。

此伺服器將包含 GraphQL 結構描述以及解析器。對於此專案,您將使用 GraphQL Yoga。

若要開始使用,請在您一開始複製的入門儲存庫中,在您的終端機中執行以下命令

graphql 套件是 GraphQL 的 JavaScript 參考實作。它是 graphql-yoga 的同層級相依性。

定義應用程式的結構描述

接下來,您需要定義 GraphQL 結構描述。在專案的根資料夾中建立新的 graphql 目錄,並在其中建立新的 schema.ts 檔案。您將定義 Link 物件以及傳回所有連結的查詢。

定義解析器

您需要做的下一件事是為 links 查詢建立解析器功能。若要執行此操作,請建立 /graphql/resolvers.ts 檔案並新增以下程式碼

resolvers 是一個物件,您可以在其中定義每個查詢和變異的實作。Query 物件內的功能必須與結構描述中定義的查詢名稱相符。變異也是如此。此處 links 解析器功能傳回物件陣列,其中每個物件的類型都是 Link

建立 GraphQL 端點

若要建立 GraphQL 端點,您將利用 Next.js 的 API 路由/pages/api 資料夾內的任何檔案都會對應到 /api/* 端點,並被視為 API 端點。

繼續建立 /pages/api/graphql.ts 檔案並新增以下程式碼

您建立了一個新的 GraphQL Yoga 伺服器執行個體,它是預設匯出。您也使用 createSchema 功能建立了一個結構描述,該功能採用類型定義和解析器作為參數。

然後,您使用 graphqlEndpoint 屬性將 GraphQL API 的路徑指定為 /api/graphql

最後,每個 API 路由都可以匯出 config 物件以變更預設組態。此處停用了主體剖析。

使用 GraphiQL 發送查詢

完成先前的步驟後,執行以下命令來啟動伺服器

當您導覽至 https://127.0.0.1:3000/api/graphql/ 時,您應該會看到以下頁面

GraphiQL Playground for running queries

GraphQL Yoga 提供了一個稱為 GraphiQL 的互動式遊樂場,您可以使用它來探索 GraphQL 結構描述並與您的 API 互動。

使用以下查詢更新右側索引標籤上的內容,然後按下 CMD/CTRL + Enter 以執行查詢

GraphiQL Playground with an example query

回應應該會顯示在左側面板上,類似於上面的螢幕擷取畫面。

文件瀏覽器 (頁面上的左上角按鈕) 可讓您個別探索每個查詢/變異,查看不同的所需引數及其類型。

GraphiQL documentation explorer

初始化 Prisma Client

到目前為止,GraphQL API 會在解析器功能中傳回硬式編碼的資料。您將在這些功能中使用 Prisma Client,以將查詢傳送至資料庫。

Prisma Client 是一個自動產生、類型安全、查詢建置器。若要能夠在您的專案中使用它,您應該先執行個體化一次,然後在整個專案中重複使用它。繼續在專案的根資料夾中建立 /lib 資料夾,並在其中建立 prisma.ts 檔案。接下來,將以下程式碼新增至其中

首先,您要建立新的 Prisma Client 執行個體。然後,如果您不在生產環境中,Prisma 將會附加到全域物件,以便您不會耗盡資料庫連線限制。如需更多詳細資訊,請查看 Next.js 和 Prisma Client 最佳實務的文件。

使用 Prisma 查詢資料庫

現在您可以更新解析器,以從資料庫傳回資料。在 /graphql/resolvers.ts 檔案中,更新 links 函式為以下程式碼

如果一切設定正確,當您前往 GraphiQL,網址為 https://127.0.0.1:3000/api/graphql 並重新執行 links 查詢時,資料應從您的資料庫中檢索。

目前 GraphQL 設定的缺陷

當 GraphQL API 的複雜度增加時,目前手動建立 schema 和解析器的工作流程可能會降低開發人員的生產力

  • 解析器必須與 schema 具有相同的結構,反之亦然。否則,您可能會遇到錯誤且不可預測的行為。當 schema 演進或解析器實作變更時,這兩個組件可能會意外地失去同步。
  • GraphQL schema 定義為字串,因此 SDL 程式碼沒有自動完成和建置時期的錯誤檢查。

為了解決這些問題,可以使用 GraphQL code-generator 等工具的組合。或者,您可以在建置具有解析器的 schema 時使用程式碼優先方法。

使用 Pothos 的程式碼優先 GraphQL API

Pothos 是一個 GraphQL schema 建構函式庫,您可以在其中使用程式碼定義您的 GraphQL schema。這種方法的價值主張是您正在使用程式語言來建置您的 API,這有多重好處

  • 無需在 SDL 和您用於建置業務邏輯的程式語言之間切換上下文。
  • 來自文字編輯器的自動完成
  • 類型安全 (如果您使用 TypeScript)

這些好處有助於提供更好的開發體驗,並減少摩擦。

在本教學中,您將使用 Pothos。它也為 Prisma 提供了一個很棒的 plugin,可在您的 GraphQL 類型和 Prisma schema 之間提供良好的開發體驗和類型安全。

注意:Pothos 可以在類型安全的方式下與 Prisma 一起使用,而無需使用 plugin,但是該過程非常手動。請參閱此處的詳細資訊。

若要開始使用,請執行以下命令以安裝 Pothos 和 Pothos 的 Prisma plugin

接下來,將 pothos generator block 新增到您的 Prisma schema 中,就在 client generator 的正下方

執行以下命令以重新產生 Prisma Client 和 Pothos 類型

接下來,建立 Pothos schema builder 的一個執行個體作為可共用模組。在 graphql 資料夾中,建立一個名為 builder.ts 的新檔案,並新增以下程式碼片段

  1. 定義所有將需要的函式庫和公用程式
  2. 建立新的 SchemaBuilder 執行個體
  3. 定義將在建立 GraphQL schema 時使用的靜態類型
  4. 定義 SchemaBuilder 的選項,例如 plugins 和將使用的 Prisma Client 執行個體
  5. 建立具有名為 ok 的查詢的 queryType,該查詢傳回布林值

接下來,在 /graphql/schema.ts 檔案中,將 typeDefs 替換為以下程式碼,這將從 Pothos 的 builder 建立 GraphQL schema

最後,更新 /pages/api/graphql.ts 檔案中的匯入

確保伺服器正在執行並導覽至 https://127.0.0.1:3000/api/graphql。您將能夠傳送具有 ok 欄位的查詢,這將傳回 true

Query

使用 Pothos 定義 schema

第一步是使用 Pothos 定義 Link 物件類型。繼續建立 /graphql/types/Link.ts 檔案,新增以下程式碼

由於您正在使用 Pothos 的 Prisma plugin,因此 builder 執行個體提供了公用程式方法來定義您的 GraphQL schema,例如 prismaObject

prismaObject 接受兩個引數

  • name:您想要公開的 Prisma schema 中模型的名稱。
  • options:用於定義您要公開的類型的選項,例如描述、欄位等。

注意:您可以使用 CTRL + Space 叫用編輯器的 intellisense 並檢視可用的引數。

fields 屬性用於定義您想要從 Prisma schema 中使用 "expose" 函式公開的欄位。在本教學中,我們將公開 idtitleurlimageUrlcategory 欄位。

t.relation 方法用於定義您希望從 Prisma schema 公開的關係欄位。

現在建立新的 /graphql/types/User.ts 檔案,並將以下程式碼新增到程式碼中以建立 User 類型

由於 Prisma schema 中的 emailimage 欄位可為 null,因此請將 nullable: true 作為第二個引數傳遞給 expose 方法。

從產生的 schema 中「公開」role 欄位類型時,role 欄位的預設類型。在上面的範例中,您已定義一個明確的列舉類型,稱為 Role,然後用於解析 role 的欄位類型。

若要使 schema 中定義的物件類型在 GraphQL schema 中可用,請將您剛才在 graphql/schema.ts 檔案中建立的類型的匯入新增進去

使用 Pothos 定義查詢

graphql/types/Link.ts 檔案中,在 Link 物件類型定義下方新增以下程式碼

在以上程式碼片段中

  1. 定義名為 links 的查詢類型。
  2. 定義將解析為產生的 Prisma Client 類型的欄位。
  3. 指定 Pothos 將用於解析欄位的欄位。在此情況下,它解析為 Link 類型的陣列
  4. 定義查詢的邏輯。

解析器函式中的 query 引數會將 selectinclude 新增到您的查詢中,以便在單個請求中解析盡可能多的關係欄位。

現在,如果您回到 GraphiQL,您將能夠傳送一個查詢,該查詢傳回資料庫中的所有連結。

link query response on GraphiQL

用戶端 GraphQL 查詢

對於此專案,您將使用 Apollo Client。您可以傳送常規 HTTP POST 請求以與您剛才建置的 GraphQL API 互動。但是,當使用 GraphQL Client 時,您可以獲得很多好處。

Apollo Client 負責請求和快取您的資料,以及更新您的 UI。它還包括用於查詢批次處理、查詢重複資料刪除和分頁的功能。

在 Next.js 中設定 Apollo Client

若要開始使用 Apollo Client,請執行以下命令將其新增到您的專案中

接下來,在 /lib 目錄中建立一個名為 apollo.ts 的新檔案,並將以下程式碼新增到其中

您正在建立一個新的 ApolloClient 執行個體,您正在將組態物件與 uricache 欄位傳遞給該執行個體。

  • uri 欄位指定您將與之互動的 GraphQL 端點。當應用程式部署時,這將變更為生產 URL。
  • cache 欄位是 InMemoryCache 的執行個體,Apollo Client 使用它在擷取查詢結果後快取查詢結果。

接下來,前往 /pages/_app.tsx 檔案並將以下程式碼新增到其中,這會設定 Apollo Client

您正在使用 Apollo Provider 包裝全域 App 元件,以便專案的所有元件都可以傳送 GraphQL 查詢。

注意:Next.js 支援不同的資料擷取策略。您可以從伺服器端、用戶端或在建置時期擷取資料。若要支援分頁,您需要從用戶端擷取資料。

使用 useQuery 傳送請求

若要在您的前端使用 Apollo client 載入資料,請更新 /pages/index.tsx 檔案以使用以下程式碼

您正在使用 useQuery hook 將查詢傳送到 GraphQL 端點。此 hook 具有 GraphQL 查詢字串的必要參數。當元件呈現時,useQuery 會傳回一個物件,其中包含三個值

  • loading:一個布林值,用於判斷是否已傳回資料。
  • error:一個物件,其中包含在傳送查詢後發生錯誤時的錯誤訊息。
  • data:包含從 API 端點傳回的資料。

在您儲存檔案並導覽至 http://loclahost:3000 之後,您將看到從資料庫擷取的連結清單。

分頁

AllLinksQuery 傳回您在資料庫中的所有連結。隨著應用程式的成長和您新增更多連結,您將擁有一個大型 API 回應,這將需要很長時間才能載入。而且解析器傳送的資料庫查詢也會變慢,因為您正在使用 prisma.link.findMany() 函式傳回資料庫中的連結。

改善效能的常見方法是新增對分頁的支援。這是當您將大型資料集分割成較小的區塊時,這些區塊可以根據需要請求。

實作分頁的方式有很多種。您可以執行編號頁面,例如 Google 搜尋結果,或者您可以執行無限捲動,例如 Twitter 的 feed。

Infinite scrolling GIF by https://dribbble.com/artrayd

資料庫層級的分頁

現在在資料庫層級,您可以使用兩種分頁技術:基於偏移量的分頁和基於游標的分頁。

  • 基於偏移量:您跳過一定數量的結果並選取有限的範圍。例如,您可以跳過前 200 個結果,然後僅取 10 個。這種方法的缺點是它在資料庫層級無法擴展。例如,如果您跳過前 200,000 筆記錄,資料庫仍然必須遍歷所有記錄,這將影響效能。

如需有關為何您可能想要使用基於偏移量的分頁的更多資訊,請查看文件

Offset-based pagination

  • 基於游標的分頁:您使用游標來為結果集中的位置加上書籤。在後續請求中,您可以直接跳到該已儲存的位置。類似於您如何透過索引存取陣列。

游標必須是唯一的循序欄 - 例如 ID 或時間戳記。這種方法比基於偏移量的分頁更有效率,並且將是您在本教學中使用的那種方法。

Cursor-based pagination

GraphQL 中的分頁

若要使 GraphQL API 支援分頁,您需要將 Relay Cursor Connections Specification 引入 GraphQL schema。這是關於 GraphQL 伺服器應如何公開分頁資料的規格。

以下是 allLinksQuery 的分頁查詢的外觀

查詢採用兩個引數,firstafter

  • first:一個 Int,用於指定您希望 API 傳回多少個項目。
  • after:一個 ID 引數,用於為結果集中的最後一個項目加上書籤,這是游標。

此查詢傳回一個物件,其中包含兩個欄位,pageInfoedges

  • pageInfo:一個物件,可協助用戶端判斷是否還有更多資料要擷取。此物件包含兩個欄位,endCursorhasNextPage
    • endCursor:結果集中最後一個項目的游標。此游標的類型為 String
    • hasNextPage:API 傳回的布林值,讓用戶端知道是否還有更多頁面可以擷取。
  • edges 是一個物件陣列,其中每個物件都有 cursornode 欄位。node 欄位在此處傳回 Link 物件類型。

您將實作單向分頁,其中在頁面首次載入時請求某些連結,然後使用者可以透過按一下按鈕來擷取更多連結。

或者,您可以讓使用者在捲動到頁面結尾時發出此請求。

其運作方式是,您在頁面首次載入時擷取一些資料。然後在按一下按鈕後,您會向 API 傳送第二個請求,其中包含您想要傳回的項目數和游標。然後傳回資料並顯示在用戶端上。

How Pagination works client-side

注意:雙向分頁的範例是聊天應用程式,例如 Slack,您可以在其中透過向前或向後移動來載入訊息。

修改 GraphQL schema

Pothos 提供了一個 plugin,用於處理具有節點、連線和其他有用的公用程式的 relay 樣式游標分頁

使用以下命令安裝 plugin

更新 graphql/builder.ts 以包含 relay plugin。

更新解析器以從資料庫傳回分頁資料

若要使用基於游標的分頁,請對 links 查詢進行以下更新

prismaConnection 方法用於建立 connection 欄位,該欄位也會預先載入該連線內的資料。

以下圖表摘要說明分頁在伺服器上的運作方式

How Pagination works on the server

用戶端上使用 fetchMore() 的分頁

既然 API 支援分頁,您可以使用 Apollo Client 在用戶端擷取分頁資料。

useQuery hook 傳回一個物件,其中包含 dataloadingerrors。但是,useQuery 也傳回一個 fetchMore() 函式,用於處理分頁,並在傳回結果時更新 UI。導覽至 /pages/index.tsx 檔案並更新它以使用以下程式碼來新增對分頁的支援

您首先將 variables 物件傳遞給 useQuery hook,其中包含一個名為 first 的索引鍵,其值為 2。這表示您將擷取兩個連結。您可以將此值設定為您想要的任何數字。

data 變數將包含從對 API 的初始請求傳回的資料。

然後,您要從 pageInfo 物件中解構 endCursorhasNextPage 值。

如果 hasNextPagetrue,我們將顯示一個具有 onClick 處理常式的按鈕。此處理常式傳回一個函式,該函式呼叫 fetchMore() 函式,該函式接收具有以下欄位的物件

  • 一個 variables 物件,它採用從初始資料傳回的 endCursor
  • updateQuery 函式,負責透過將先前的結果與從第二個查詢傳回的結果結合來更新 UI。

如果 hasNextPagefalse,則表示沒有更多連結可以擷取。

如果您儲存並且您的應用程式正在執行,您應該能夠從資料庫擷取分頁資料。

摘要與後續步驟

恭喜!您已成功完成本課程的第二部分!如果您遇到任何問題或有任何疑問,請隨時在我們的 Slack 社群中聯絡我們。

在本部分中,您學習了

  • 使用 GraphQL 而不是 REST 的優點
  • 如何使用 SDL 建置 GraphQL API
  • 如何使用 Pothos 建置 GraphQL API 及其提供的優點
  • 如何在您的 API 中新增對分頁的支援,以及如何從用戶端傳送分頁查詢

在課程的下一部分中,您將

  • 使用 Auth0 新增驗證以保護 API 端點的安全,這樣一來,只有登入的使用者才能檢視連結
  • 建立 mutation,以便登入的使用者可以將連結加入書籤
  • 為建立連結建立僅限管理員的路徑
  • 設定 AWS S3 以處理檔案上傳
  • 新增 mutation 以作為管理員建立連結

請勿錯過下一篇文章!

註冊 Prisma 電子報