iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
Modern Web

React + GraphQL 全端練習筆記系列 第 28

仿Trello - 前端 Apollo Client 串接 GraphQL API

本系列文以製作專案為主軸,紀錄小弟學習React以及GrahQL的過程。主要是記下重點步驟以及我覺得需要記憶的部分,有覺得不明確的地方還請留言多多指教。

後端API建立好了,現在回到前端來發送請求取得資料。

Apollo 針對前端也有工具,Apollo client,可以在發送GraphQL請求後建立前端cache,在前端發送重複請求時直接從快取存取資料,降低向Server請求的頻率。

這個Cache其實就如同Redux的Store,所以除了向Server請求資料外,Apollo Client也能用於前端狀態管理,好處在於可以用GraphQL的方式存取local state,靈活性高。

目前的 Apollo 版本沒有跟Redux的store集成的方法,只能各管各的,或是直接取代Redux 用 Apollo 做 local state的管理,不過這邊只是學習筆記,就不弄大工程取代掉Redux,簡單示範如何用 Apollo Client 進行 GraphQL 請求。

安裝

回到 client資料夾,用 npm 安裝套件:

npm install @apollo/client graphql

在 index.js 中建立 Apollo client 實例:

//index.js
//...
import { ApolloClient, InMemoryCache } from "@apollo/client";

const client = new ApolloClient({
  uri: "http://localhost:4000/",  //指定API網址
  cache: new InMemoryCache(), //建立 cache
});
//...

然後將 client 應用給 APP:

//index.js
//...
import {  ApolloProvider } from "@apollo/client";

//...

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client}>  //將APP包裝
      <Provider store={store}>   //這是原本的Redux Store
        <App />
      </Provider>
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

這樣發送 GraphQL 請求的準備就完成了。

useQuery

Apollo Client 在2.6版後改以 hook 的方式進行 query 跟 mutation。而要進行請求,要先撰寫graphQL 請求字串,在提供給hook 使用。

以query lists為例,先將 useQuery 跟 gql 標籤引入KanBan:

//KanBan.jsx
import { useQuery, gql } from "@apollo/client";

const GET_LISTS = gql`
  query GetLists {
    lists {
      id
      title
      todos {
        id
        name
      }
    }
  }
`;

注意必須要以 gql 標籤將字串轉為請求物件。

接著就能在元件中以 useQuery 發送請求取得資料

//KanBan.jsx
export default function KanBan({ lists, editState, kanBanMenuState }) {
  const { loading, error, data } = useQuery(GET_LISTS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :(</p>;
  console.log(data.lists);

  //...
}

useQuery的回傳值中有一些請求的進行狀態,像是loading為true時表示請求還在處理中,就可以利用這個布林值先渲染載入畫面。

而當請求完成後就能從data取得資料用於元件渲染,或是error取得錯誤訊息。

useMutation

跟 useQuery 一樣可以用 useMutation 進行 mutation 請求,順便示範如何在請求中帶入參數。

一樣先引入 fucntion 後用 gql 編寫請求:

//List.jsx
import { gql, useMutation } from "@apollo/client";

const ADD_TODO = gql`
  mutation AddTodo($name: String!, $listId: Int!) {
    addTodo(name: $name, listId: $listId) {
      id
      name
    }
  }
`;

注意宣告 AddTodo 時宣告了參數與其型別,然後其中的請求時再以這些參數帶入請求。

將ADD_TODO用於 mutation:

const List = React.forwardRef(...)=> {

const [addTodo] = useMutation(ADD_TODO);

//...
}

useMutation 回傳值第一個是執行請求的function,可以在click時呼叫:

//NewTodo.jsx

//...

function handleAddTodo(e) {
if (e.target.value.trim()) {
  addTodo({ variables: { listId: listId, name: e.target.value } });
}

e.target.value = "";
toggleShowNew();
}
//...

要提供物件作為參數給addTodo,並以 variables 宣告帶入請求的參數。

成功執行 mutation 後應該會發現頁面並沒有相應的變化,因為 mutatoin 修改完 Server、資料庫的訊息後本地端的cache並不一定會自動更新,可以重新發送query請求不過那太耗資源了,應該要在mutation後利用回傳的訊息編輯cache。

編輯 cache 還挺複雜的,就分篇吧。

References:


上一篇
仿Trello - Prisma client CRUD
下一篇
仿Trello - Apollo client cache 操作
系列文
React + GraphQL 全端練習筆記30

尚未有邦友留言

立即登入留言