iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 30
1
Modern Web

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

Apollo Client Network Errors

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

如果 Client 端的 GraphQL query 指令中的 fields 有誤,向 Server 請求後 React 只會出現請求失敗訊息。

像是執行以下 mutation:

const ADD_LIST = gql`
  mutation AddList($listTitle: String!) {
    addList(listTitle: $listTitle) {
      id
      name #這裡應該是 title 才對
    }
  }
`;

Server 端應回傳的 List 形別只有 title 欄位,沒有 name 欄位,導致請求發送後會收到 status code 400 錯誤訊息:

但並不會顯示是哪個 GraphQL 請求的哪個部分錯誤,這樣要 debug 就傷腦筋了, 所以要另外設定 Apollo Client 的 Error handling 顯示更精確的錯誤訊息。

Apollo Link


(圖片來源: Apollo docs)

有關網路通訊以及GraphQL的錯誤訊息會需要利用 Apollo Link 來存取。

Apollo Link 用於設定每當 Apollo Client 執行 GraphQL 請求後的額外操作,可以串起一系列不同的 Link ,例如第一個 Link 將請求資訊寫入 Log ,第二個 Link 在 Header 添加資訊,最後一個 Link 再向 Server 請求這樣。

onError Link

Apollo 已經有提供一些現成的 Link 物件,其中一個是 onError 這個 Link,使用上會像這樣:

import { onError } from "@apollo/client/link/error";

const link = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
      ),
    );

  if (networkError) console.log(`[Network error]: ${networkError}`);
});

這是官方範例,在出現 GraphQL 錯誤或網路通訊錯誤時顯示訊息。

有了這個 Link 後,還不能直接應用到 Apollo Client 上,要先搭配發送請求給 Server 的 Link。

HttpLink

目前的 ApolloClient instance 長這樣:

const client = new ApolloClient({
  uri: "http://localhost:4000/",
  cache: new InMemoryCache(),
});

在 ApolloClient 的設定中,可以用 uri 或 link 指定傳送請求的 server,如果兩者並存的話會以 link 優先。
相較 uri , link 可以制定更詳細的請求設定。

使用 link 向 server 發送請求:

import { HttpLink } from "@apollo/client";

const link = new HttpLink({ uri: "http://localhost:4000/" });

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: link,
});

如果想串接更多 Link 模塊,就需要用 HttpLink 負責最後向 Server 傳送請求的工作。

串接多個 Link

接著要將錯誤訊息處理跟請求發送的 Link 串起來,設定給 ApolloClient。

Apollo Client 中的 from 方法,可以接收包含數個 Link 的陣列,包成一個 Link 物件使用。

const link = from([ Link1, Link2 , ... ,  terminatingLink]);

注意無論中間過程為何,負責向 Server 執行請求的 terminatingLink 必須放在陣列的最後一位。

將 ErrorLogLink 跟 terminatingLink 串接後給 ApolloClient 用:

import {
  ApolloClient,
  InMemoryCache,
  from,
  HttpLink,
} from "@apollo/client";
import { onError } from "@apollo/client/link/error";

const ErrorLogLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors)
    graphQLErrors.map(({ message, locations, path }) =>
      console.log(
        `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
      )
    );

  if (networkError) console.log(`[Network error]: ${networkError}`);
});

const RequestLink = new HttpLink({
  uri: process.env.REACT_APP_APOLLO_SERVER_URL,
});

const link = from([ErrorLogLink, RequestLink]);

const client = new ApolloClient({
  link: link,
  cache: new InMemoryCache(),
});

這樣當執行了有問題的 GraphQL 請求後,就能在瀏覽器的 console 看見錯誤訊息,知道是哪個 field 出問題了:

References:


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

尚未有邦友留言

立即登入留言