Coding Hero

We solve your problems

在React專案裡加入Apollo Client

2019-08-28 Frankapollo client

本篇要介紹的是 GraphQL Apollo Client 的基本安裝。

What is GraphQL?


GraphQL 是一個開源的 API 數據查詢和操作語言及實現為了實現上述操作的相應運行環境。2012 年,GraphQL 由 Facebook 內部開發,2015 年公開公布。2018 年 11 月 7 日,Facebook 將 GraphQL 項目轉移到新成立的 GraphQL 基金會(隸屬於非營利性的 Linux 基金會)。

GraphQL 相較於 REST 以及其他 web service 架構提供了一種高效、強大和靈活的開發 web APIs 的方式。它通過由客戶端根據所需定義數據結構,同時由服務端負責返回相同數據結構的對應數據的方式避免了服務端大量冗餘數據的返回,但與此同時也意味著這種方式不能有效利用起查詢結果的 web 緩存。GraphQL 這種查詢語言所帶來的靈活性和豐富性的同時也增加了複雜性,使得這項技術對於簡單 APIs 並不是好的選擇。

GraphQL 支持數據讀取、寫入(操作)和數據變更訂閱(實時更新)。

主要的 GraphQL 客戶端有 Apollo ClientRelay. GraphQL 的服務端在多個語言都有實現包括 Haskell, JavaScript, Python, Ruby, Java, C#, Scala, Go, Elixir, Erlang, PHP, R,和 Clojure.

以上簡介節錄來自 維基百科

GraphQL

為什麼要使用 GraphQL,它有哪些好處?


主要是解決傳統 RESTful 的問題,同時縮短前端與後端的開發時間,可做到程式即文檔的查詢,屬於強型別的查詢語言,並且可以在 client 自行定義結構。講個白話一點的比喻,就是把查資料當成去吃自助餐,你想吃什麼就拿什麼,完全可以自己組,不需要的資料可以完全忽略他們,不像傳統 API 只能一次給你一整包,在資料一複雜的情況下,可能資料還沒找到,眼睛就先已經花了。

除了查找資料方便外,也有一些其他的好處,例如內建的 playground、後端可以在 resolover 裡自由地建立欄位間的關聯、以及一些前端如奇門遁甲般的奇技淫巧emoji-thumbsupemoji-smiling_imp(這部分會再開篇幅細講)。詳細 GraphQL 的優缺點介紹還可以參考這篇網路上人家寫好的 優文 (這個部落格的 GraphQL 系列文章比較偏重後端 Apollo Server 的部分,很多 features 講得算滿細的,推薦)。



在 React 專案裡使用 Apollo Client


在這裡我們會把介紹的重點放在Apollo Client,算是目前最主流的 GraphQL 前後端解決方案,文檔算相當詳盡,社群資源與開源 package 算豐富,唯一缺憾是繁體中文資料稍嫌不足。

首先要注意的是,在 Apollo Client 2.6 已經推出了用 hooks 為主流的開發方式,在 2.5 之前,仍然是使用 component 搭配 render props 的方式為主,兩種方式之後皆會介紹。

Migration notes:

  • 要使用 hooks ,使用 npm 安裝此套件:
$ npm install @apollo/react-hooks

  • 若專案較舊,仍然有使用 class-based component ,你要安裝的是這個:
$ npm install @apollo/react-components

若先前已經有裝 react-apollo 這個 package 的話,請將其移除。

  • 只想用 Apollo 提供的 HOC 的話,安裝以下:
$ npm install @apollo/react-hoc

同第二個套件,若你要使用的是 HOC,先前已經有裝 react-apollo 這個 package 的話,請將其移除。

  • 假如以上三個 package 的 features 都想使用的話,安裝以下:
$ npm install react-apollo



安裝流程

npm install

$ npm install apollo-boost @apollo/react-hooks graphql

index.js 設定

在官方的文檔裡面有段教學,最基礎建立一個 Apollo Client 的方式如下:

import ApolloClient from "apollo-boost"

const client = new ApolloClient({
  uri: "https://48p1r2roz4.sse.codesandbox.io"
})

這邊其實有個非常重要的小坑要注意,一般來說官方範例使用的 apollo-boost 套件比較屬於一些陽春型的基礎功能,假如將來需要使用各種拓展功能,例如 error link 或者 subscription 的話,你可能會發現為何 apollo-boost 裡提供的 ApolloClient 為何跟教學範例裡的 signature 有點不大一樣,或者有些 options 不管怎麼用就是出不來,一直報錯,仔細觀察後會發現需要使用進階功能的範例引用的是 react-apollo 裡面的 ApolloClient ,這個版本的 ApolloClient 才是有完整功能的 ApolloClient ,因此為了避免踩一些不必要的坑,建議在一開始就使用 react-apollo 裡面的 ApolloClient ,而 apollo-boost 這個套件裡面的功能,一般來說用到的機會不多,頂多就是 import gql 進而使用 graphql 的語法而已(如下例)。

import { gql } from "apollo-boost"

(註: Apollo 官方在文檔裡有提及之後會有將 react-apollo 這個 package 移除的計畫,所以你看到此文章時若版本已經更新,記得要去找一下最新版的完整版 ApolloClient 是在哪個 package 裡面!)

Provider 設定

現在很多主流的 state management 套件都是類似的設定,例如 Redux ,在最上層的 component 做一個 Provider,將狀態利用 context 或 HOC 的方式傳入, Apollo Client 也不例外,配合前面 initialize 出來的 ApolloClient instance,加上下述設定,即可完成 Apollo Client 陽春版的初始設定。

import React from "react"
import { render } from "react-dom"
import { ApolloProvider } from "@apollo/react-hooks"
import ApolloClient from "apollo-boost"

const client = new ApolloClient({
  uri: "https://48p1r2roz4.sse.codesandbox.io"
})

const App = () => (
  <ApolloProvider client={client}>
    <div>
      <h2>My first Apollo app 🚀</h2>
    </div>
  </ApolloProvider>
)

render(<App />, document.getElementById("root"))