iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
1
Modern Web

Think in GraphQL系列 第 26

GraphQL 前端: Apollo Client 攜手 React 擁抱 GraphQL

header

我們今天要來介紹 Apollo Client ,這個套件是目前 GraphQL + React 最有名的套件之ㄧ,而且可以支援其他框架。

今天會簡單介紹如何設定以及利用之前的 project 來寫出一個支援 GraphQL 的前端網頁!

PS 如果懶得打開程式碼,也可以使用我之前推薦的 Code Sandbox ,然後打開一個 React 專案,雖然跟我本篇所用的 create-react-app 的資料結構有些不同,但對於有基本 React 概念的朋友應該不成問題。


1. 環境設定 + 範例上手

開始之前我們要先開啟專案以及設定一些環境。

安裝 create-react-app

這邊我們選用最通用的 boilerplate facebook/create-react-app來做示範。

~ $ npx create-react-app react-graphql
~ $ cd react-graphql
~/react-graphql $ npm start

成功初始化專案後,你會得到一個基本的 react 專案。

img

  • src : 主要程式碼
    • index.js : 程式入口點,不過今天不會碰到
    • App.js : 主畫面
  • public : 放置一些 html, css 等 assets
    • index.html : 頁面模板

以及啟動後的畫面:

img

安裝 GraphQL 與 Apollo 套件

這裡我們需要以下的套件,

  • apollo-boost 裡面包裹了所有你設定 Apollo Client 所需要的套件。
  • react-apollo 一層與 React 整合起來的 View 。
  • graphql 用來 parse GraphQL query 的套件。

資料參考: https://www.apollographql.com/docs/react/essentials/get-started.html#packages

~/react-graphql $ npm install --save apollo-boost react-apollo graphql

接著就用這些套件來設定 Apollo Client !

2. 設定 Apollo client

首先進入 src/App.js ,引入 ApolloClient 並作初始化,不過初始化時要傳入一個 GraphQL API uri 才能正確啟動 ApolloClient,這邊有幾種選擇:

  1. 自己在 local 開一個 GraphQL Server 然後把網址填進去
  2. 使用線上有的 GraphQL API 網址
  3. 使用 Apollo LaunchPad,他可以自行幫你維護一個簡單的 server 供你測試。

為 demo 方便,我就使用第三種,可以參考我之前寫好的 LaunchPad 範例 ,裡面有 user 跟 post ,大家可以直接引用裡面的 API 網址 (https://z5r11749r7.lp.gql.zone/graphql) ,或是登入 Github 後 Fork 我的範例。

// src/App.js
import ApolloClient from 'apollo-boost';

const client = new ApolloClient({
  uri: 'https://z5r11749r7.lp.gql.zone/graphql'
});

接著同樣在 src/App.js ,我們將引入 ApolloProvider 進入 react , ApolloProvider 能夠連接 Apollo Client 與 React ,將 Apollo Client 索取到的資料引入 React 。

// src/App.js
import { ApolloProvider } from "react-apollo";
...

class App extends Component {
  render() {
    return (
      <ApolloProvider client={client}>
        <div>
          <h2>My first Apollo app ?</h2>
        </div>
      </ApolloProvider>
    );
  }
}

需注意 ApolloProvider 預設下會建立自己的 Redux store 去管理 queries 與 queries 的結果,因此可以不需要再引入 Redux ,而如果是想將 ApolloProvider 引入現有 React & Redux 專案的話可參考 這個連結

有了 clientApolloProvider ,接著讓我們看如何使用它們做 GraphQL query 。配合我所提供的 Apollo LaunchPad 範例,我將會利用這個 query :

img

讓我的網頁能夠呈現一個簡單的使用者列表:

img

3. 使用 Query

讓我們先建立一個 src/Users.js 檔案來取得這個 user 列表並印出所有人的 name

這裡會用到兩個外部套件,分別為

  • import { gql } from "apollo-boost"

    之前有用過 server 的應該對於 gql tag 不陌生。這個 tag 可以直接幫我們建立一個 GraphQL query 物件。

  • import { Query } from "react-apollo"

    這裡 react-apollo 提供了一個 Query component 讓我們可以使用內建的 function 連接到外部 GraphQL API 。 Query component 可以說是整個 Apollo 專案最重要的組成之一,而我們只需要傳入 query 物件進去 component props 就可以開始使用。

    另外我們還需要在 component 內提供一個 render function , render function 裡面會代入 loading, error, data 三個參數供我們依照狀況做出不同 render。

    想知道更多請看 官方文件

// src/Users.js
import React from "react";
import { Query } from "react-apollo";
import { gql } from "apollo-boost";

const getUsersQuery = gql`
  {
    users {
      id
      name
      email
      age
    }
  }
`;

const Users = () => (
  <Query query={getUsersQuery}>
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;
      // 最重要的就是從 data 裡面取得資料
      const lists = data.users.map(currentUser => (
        <li key={currentUser.id}> {currentUser.name} </li>
      ));

      return (
        <div>
          <ul style={{ "list-style-type": "none" }}>{lists}</ul>
        </div>
      );
    }}
  </Query>
);
export default Users;

有了 User name 列表後,讓我們將他引入 src/App.js

// src/App.js
...
import Users from "./Users";
...

function App() {
  return (
    <ApolloProvider client={client}>
      <div>
        <Users />
      </div>
    </ApolloProvider>
  );
}

啟動 npm start 後可以看見成果了!

img

4. 整理 UI

讓我們把剩下的資料顯示出來並編排好。回到 src/Users.js ,把 user 其他資料也顯示出來。

// src/User.js

const Users = () => (
  <Query query={getUsersQuery}>
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;
      const lists = data.users.map(currentUser => (
        <li key={currentUser.id}>
          <li>id: {currentUser.id}</li>
          <li>name: {currentUser.name} </li>
          <li>email: {currentUser.email}</li>
          <li>age: {currentUser.age}</li>
          <br />
        </li>
      ));

      return (
        <div>
          <ul style={{ "list-style-type": "none" }}>{lists}</ul>
        </div>
      );
    }}
  </Query>
);

就可以得到結果:

img


是不是很簡單呢!之後會講解如何應用到 stage management 。另外我也有在底下附上本篇的程式碼範例:

Edit React-GraphQL

先說明一下,其實 Apollo Client 也跟 Apollo Server 一樣,有分第一代跟第二代。 Apollo Server 1 只是一個 GraphQL middleware 而已,而 Apollo Server 2 整合 express, body-parser, graphql-tag, graphql-tools 等工具,一次滿足你所有需求。

同樣的, Apollo Client 也僅有結合 GraphQL 與 Redux store 管理功能而已,而第二代的 Apollo Boost 則是將 Apollo Client 以及其他常用套件如 apollo-cache-inmemory, apollo-link-http, apollo-link-error, apollo-link-state 等等,並且支援了 Query 和 Mutation Component 支援。

提到這些主要是想要提醒如果大家在網路上看到的其他範例明明都用 Apollo Client 但用法卻大不同,那就可能是因為使用的版本不同。


Reference:


上一篇
Think in GraphQL - Schema Mutation 設計守則 - 2
下一篇
GraphQL 前端 (1) - 使用 React + Apollo Client 設計一個部落格系統
系列文
Think in GraphQL30

尚未有邦友留言

立即登入留言