Apollo Clientのエラーポリシーやエラーハンドリングメモ
Apollo ClientのエラーポリシーやApollo Linkを使ってエラーハンドリングをする方法をメモしています。
Apollo Clientの通信時に発生するエラー
「GraphQLエラー」と「ネットワークエラー」の2つがあります。
- GraphQLエラー: シンタックスエラー、バリデーションエラー、リゾルバーエラーなどGraphQLのクエリに起因するエラーです。
- ネットワークエラー: サーバーとのネットワークやサーバーの状態に起因するエラーです。ステータスとしては、4xxや5xxなどのステータスコードが返ってくるようなエラーです。
GraphQLエラー
GraphQLエラーには、次のようなエラーが含まれます。
シンタックスエラーとバリデーションエラーはサーバー上でGraphQLクエリは実行されませんが、リゾルバーエラーはサーバー上でクエリは実行されて部分的なデータを返すことが可能です。
- シンタックスエラー:クエリの文法が間違っているなど
- バリデーションエラー:クエリにスキーマに存在しないフィールドが指定されているなど
- リゾルバーエラー:リゾルバーの処理を実行時にエラーが発生した場合など
// シンタックスエラーのレスポンス例
{
"errors": [
{
"message": "Cannot query field \"authoraaa\" on type \"Book\". Did you mean \"author\"?",
"locations": [ { "line": 5, "column": 5 }],
"extensions": {
"code": "GRAPHQL_VALIDATION_FAILED",
"stacktrace": [
"GraphQLError: Cannot query field \"authoraaa\" on type \"Book\". Did you mean \"author\"?",
"...",
]
}
}
]
}
ネットワークエラー
ネットワークエラーは、サーバーとの通信時のネットワークやサーバーの状態に起因するエラー(ステータスとしては、4xxや5xxなど)です。
ネットワークエラーが発生すると、error.networkError
にエラー内容が設定されます。
Apollo Clientのエラーポリシーの種類
GraphQLのリゾルバーエラーが発生したときは、レスポンスはerrors
にエラー内容が含まれます。また、data
に部分的なエラーが含まれる可能性があります。
// リゾルバーエラーのレスポンス例
// エラー時にもdataに値が部分的に含まれている
{
"errors": [
{
"message": "Invalid argument value",
"locations": [ ... ],
"path": [ ... ],
"extensions": {
"code": "BAD_INPUT",
}
}
],
"data": {
"books": [
{
"id": 1,
"title": "The Awakening",
},
],
"failedBook": null
}
}
エラーポリシーを設定することで、エラー時のデータの取り扱いを制御することができます。
エラーポリシー | 説明 |
|
|
---|---|---|---|
| エラーのみ表示 |
|
|
| エラーが起きてないように振る舞う |
| 部分的なデータが設定 |
| 部分的なデータとエラーの両方をレンダリングできる |
| 部分的なデータを設定 |
// 'all'の場合の例
const { loading, error, data } = useQuery(GET_BOOKS, {
errorPolicy: 'all',
});
if (!loading) {
console.log(data); //=> 部分的なデータが存在
console.log(error); //=> ApolloError
console.log(error.graphQLErrors) //=> GraphQLのエラーが設定
}
詳細は、GraphQL error policiesを参照ください。
Apollo Clientのエラーポリシーの設定方法
エラーポリシーを設定するには、主に次の2つの方法があります
- グローバルにエラーポリシーを設定
useQuery
などのオペレーション時にエラーポリシーを設定
グローバルにエラーポリシーを設定
ApolloClient
の初期化時にdefaultOptions
からエラーポリシーを設定することができます。
import { ApolloClient, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
cache: new InMemoryCache(),
uri: 'http://localhost:4000/',
defaultOptions: {
query: {
errorPolicy: 'all',
},
mutate: {
errorPolicy: 'ignore',
},
},
});
オペレーション時にエラーポリシーを設定
useQuery
などのフックのオプションにエラーポリシーを設定することで、個別にエラーポリシーを設定することができます。
const { loading, error, data } = useQuery(GET_TODOS, {
// 個別のクエリでerrorPolicyを指定
errorPolicy: 'all',
});
Apollo Linkで高度なエラーハンドリングをする
Apollo Link ライブラリを使うことで、高度なエラーハンドリングを実現できます。
Apollo Linkは、Apollo ClientがGraphQLサーバーと通信をする間のデータの流れを制御することができます。
Apollo ClientはデフォルトでHttpLink
を利用しており、HTTPでGraphQLサーバーにデータを通信する制御をしています。
onError
リンクを追加することで、エラー内容に基づいて処理を実行することができます。
import { ApolloClient, InMemoryCache, HttpLink, from } from "@apollo/client";
import { onError } from "@apollo/client/link/error";
// HttpLinkはGraphQLサーバーとHTTPでやり取りするために必要
const httpLink = new HttpLink({
uri: "http://localhost:4000/graphql"
});
// onErrorはGraphQLサーバーからのレスポンスのgraphQLErrorsかnetworkErrorをハンドリングできる
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) console.log(`[Network error]: ${networkError}`);
});
const client = new ApolloClient({
// linkオプションで定義したApollo Linkをチェインさせる
link: from([errorLink, httpLink]),
cache: new InMemoryCache()
});
Apollo Linkについてより詳しく知りたい場合は、Apollo Link Overviewを参照してください。