2022 年 8 月 24 日

使用 GraphQL、Prisma 和 React 實現端對端類型安全:前端

閱讀時間 13 分鐘

端對端類型安全是通過確保整個應用程式堆疊中的類型保持同步來實現的。

hero image prisma

目錄

簡介

在本系列中,您將學習如何使用 React、GraphQL、Prisma 以及其他一些將這三者結合在一起的實用工具來實現端對端類型安全。

在本節中,您將建構一個小型 React 應用程式,該應用程式會顯示使用者列表以及與每位使用者相關聯的一組訊息。這個應用程式將是唯讀的,顯示資料庫中已存在的內容。

在第一篇文章中,應用程式僅會呈現靜態資料,而不是從資料庫中獲取資料。在本系列文章的過程中,您將會改變這一點,並新增一個帶有資料庫的 GraphQL API,您的應用程式可以取用該 API 來動態呈現其資料。

您將使用的技術

這些是您將在本系列中使用的主要工具

  • Prisma 作為物件關聯對應 (ORM)
  • PostgreSQL 作為資料庫
  • Railway 用於託管您的資料庫
  • TypeScript 作為程式語言
  • GraphQL Yoga 作為 GraphQL 伺服器
  • Pothos 作為程式碼優先的 GraphQL schema 建構器
  • Vite 用於管理和搭建您的前端專案
  • React 作為前端 JavaScript 函式庫
  • GraphQL Codegen 根據 GraphQL schema 為前端產生類型
  • TailwindCSS 用於設定應用程式樣式
  • Render 用於部署您的 API 和 React 應用程式

先決條件

預設知識

雖然本系列文章將嘗試從初學者的角度詳細介紹所有內容,但以下知識將會有所幫助

  • JavaScript 或 TypeScript 的基礎知識
  • GraphQL 的基礎知識
  • React 的基礎知識

開發環境

為了跟隨提供的範例進行操作,您需要具備

使用 Vite 啟動 React 應用程式

在建構 React 應用程式時,有很多不同的入門方式。目前最簡單且最受歡迎的方式之一是使用 Vite 來搭建和設定您的應用程式。

若要開始使用,請在您希望應用程式程式碼存放的目錄中執行此命令

注意:在執行此命令之前,您不需要安裝任何套件。

此命令會在名為 react-client 的資料夾中使用 TypeScript 範本設定一個可立即使用的 React 專案。該範本隨附開發伺服器、熱模組替換和開箱即用的建置流程。

專案產生後,系統會提示您進入新目錄、安裝 node 模組並執行專案。請繼續執行以下命令來完成這些操作

一旦您的開發伺服器啟動並執行,您應該會看到類似於以下的輸出

如果您開啟該輸出中的連結,您將會看到 Vite 的 React 和 TypeScript 範本登陸頁面

清理範本

啟動器範本隨附一些您不需要的東西,因此首先要做的就是清理。

src 資料夾中,有兩件事要刪除。移除以下項目

  • App.css
  • /assets(整個目錄)

接下來,將 /src/App.tsx 的內容替換為以下組件,以便為自己提供一個乾淨的起點。

設定 TailwindCSS

您的應用程式將使用 TailwindCSS 來簡化組件的設計和樣式設定。若要開始使用,您首先需要一些新的依賴項

以上命令將安裝 TailwindCSS 在您的專案中運作所需的所有部分,包括 Tailwind CLI。使用新安裝的 CLI 在您的專案中初始化 TailwindCSS

此命令在您的專案中建立了兩個檔案

  • tailwind.config.cjs:TailwindCSS 的組態檔
  • postcss.config.cjs:PostCSS 的組態檔

tailwind.config.cjs 中,您會看到一個 content 鍵。您將在此處定義 TailwindCSS 在掃描您的程式碼並決定您正在使用哪些類別和實用程式時,應注意專案中的哪些檔案。這就是 TailwindCSS 決定需要將哪些內容捆綁到其建置和縮小的輸出中的方式。

將以下值新增至 content 鍵的陣列,以告知 TailwindCSS 查看 src 資料夾中的任何 .tsx 檔案

最後,在 src/index.css 中,您需要匯入 TailwindCSS 實用程式,這是專案中使用 TailwindCSS 所必需的。將整個檔案的內容替換為以下內容

TailwindCSS 現在已設定完成,可以開始使用了!將 src/App.tsx 中的現有 <h2> 標籤替換為此 JSX,以測試 TailwindCSS 類別是否正常運作

如果您的網頁看起來像這樣,恭喜!您已成功設定 TailwindCSS!

注意:如果沒有,請嘗試重新啟動您的開發伺服器並確保正確遵循了上述步驟。

定義並模擬您的資料

現在 TailwindCSS 已設定完成,您幾乎可以開始建構組件以顯示您的資料。您首先還需要做一件事:定義並模擬您的資料。

為了確保您的應用程式是類型安全的,您需要建立一組 TypeScript 類型來定義您的兩個資料模型:使用者和訊息。在建構這些類型之後,您將模擬一組測試資料。

首先,在 src 目錄中建立一個名為 types.ts 的新檔案

這是您將儲存此應用程式所需的所有類型檔案。在該檔案中,新增並匯出一個名為 Message 的新 type,其中包含一個名為 bodystring 欄位

此類型描述了 Message 物件中可用的內容。只有一個鍵,但在實際應用程式中,這可能包含數十個或更多欄位定義。

接下來,新增並匯出另一個名為 User 的類型,其中包含一個 string 類型的 name 欄位和一個包含 Message 物件陣列的 messages 欄位

注意:在本系列的下一節中,您將把這些手動編寫的類型替換為自動產生的類型,這些類型包含您的 API 公開資料模型的最新表示。

現在您的資料已經「描述」完成,請前往 src/App.tsx。您將在此處模擬一些資料以在您的應用程式中使用。

首先,將新的 User 類型匯入 src/App.tsx

接下來,在該檔案的 App 函數中,建立一個名為 users 的新變數,其中包含一個 User 物件陣列,其中包含一個使用者項目,該項目關聯了幾個訊息

在上面的程式碼片段中,您定義了一個具有兩個關聯訊息的單一使用者。這就是您建構此應用程式 UI 組件所需的所有資料。

顯示使用者列表

您將建構的第一個 UI 部分是顯示使用者的組件。在 src 目錄中建立一個名為 components 的新資料夾

在該資料夾中,建立一個名為 UserDisplay.tsx 的檔案

此檔案將包含使用者顯示組件。若要開始建構該組件,請建立一個名為 UserDisplay 的函數,該函數目前會傳回一個簡單的 <p> 標籤。然後匯出該函數

這將作為您組件的骨架。此處的目標是允許此組件接收一個 user 參數,並在組件內顯示該使用者的資料。

若要完成此操作,請先在 src/components/UserDisplay.tsx 的最頂端匯入您的 User 類型

您將使用此類型來描述 UserDisplay 函數中的 user 屬性應包含的內容。

在此檔案中新增一個名為 Props 的新 type,其中包含一個 User 類型的單一 user 欄位。使用該類型來描述您函數的引數(或「props」)

注意user 鍵正在函數引數中進行解構,以便輕鬆存取其值。

user 屬性允許您為您的組件提供一個 User 類型的物件。此應用程式中的每位使用者都將顯示在一個包含使用者姓名的矩形中。

將現有的 <p> 標籤替換為以下 JSX,以使用一些美觀的 TailwindCSS 樣式顯示使用者姓名

此組件現在已準備好顯示使用者的詳細資訊,但您尚未在任何地方呈現它。

前往 src/App.tsx 並匯入您的新組件。然後,取代目前的 <h2> 標籤,為 users 陣列中的每位使用者呈現組件

如果您回到瀏覽器,您應該會看到一個美觀的方框顯示您的使用者姓名!此時唯一缺少的是使用者的訊息。

顯示每位使用者的訊息

現在您可以顯示您的使用者,您將顯示使用者關聯的訊息。您將建立一種「樹狀檢視」來顯示訊息。

首先建立一個組件來顯示個別訊息。在 src/components 中建立一個名為 MessageDisplay.tsx 的新檔案

然後,將 Message 類型從 src/types.ts 匯入到新檔案中,並建立一個包含兩個鍵的 Props 類型

  • message:一個包含訊息詳細資訊的 Message 物件
  • index:一個 number 數字值,其中包含目前訊息在其父層訊息列表中的索引

結果應如下面的程式碼片段所示

完成這些步驟後,您就可以建構組件函數了。以下程式碼使用您編寫的 Props 類型來描述函數引數,使用解構取出 messageindex 值,在樣式化的容器中呈現訊息,最後匯出組件

現在是時候使用該組件了!在 src/components/UserDisplay.tsx 中,匯入 MessageDisplay 組件,並為 user.messages 陣列中的每個元素呈現一個組件

在您的瀏覽器中,您現在應該會在每位使用者的右側看到他們的訊息!

看起來很棒,但還有一件事要新增。您正在建構樹狀檢視,因此最後一步是呈現將每個訊息連接到其使用者的「分支」。

src/components 中建立一個名為 Branch.tsx 的新檔案

此組件將接收一個屬性 trunk,它指示其連結的訊息是否為列表中的第一個。

注意:這就是您需要在 MessageDisplay 組件中使用 index 鍵的原因。

將以下組件插入到該檔案中

上面的程式碼片段使用一些巧妙的 TailwindCSS 技巧呈現一個分支。如果您對 TailwindCSS 提供的功能感興趣,或者想更好地了解上面發生的事情,TailwindCSS 提供了出色的 文件,其中涵蓋了上面使用的所有類別。

為了完成此應用程式的 UI,請在您的 MessageDisplay 組件中使用新的 Branch 組件,為每個訊息呈現一個分支

回到您的瀏覽器中,您現在將看到每個訊息的分支!將滑鼠懸停在訊息上以突顯分支 ✨

總結 & 接下來的步驟

在本文中,您建構了完全類型安全應用程式的前端部分。在此過程中,您

  • 設定 React 專案
  • 設定 TailwindCSS
  • 建模並模擬了您的資料
  • 為您的應用程式建構了 UI 組件

此時,您的應用程式中的資料和類型是靜態且手動建構的。在本系列的未來章節中,您將使用程式碼生成設定動態類型定義,並使用來自資料庫的動態資料。

在下一篇文章中,您將開始建構您的 API、設定您的資料庫,並在您的專案中初始化 Prisma。

不要錯過下一篇文章!

註冊 Prisma 電子報