GrahqQLサーバーではさまざまな種類のエラーが発生します。Apollo Clientはサーバーでエラーが発生した時にエラーハンドリングをエラーポリシーやApollo Linkによって制御することができます。
エラーの種類
- 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 } }
エラーポリシーを設定することで、エラー時のデータの取り扱いを制御することができます。
エラーポリシー | 説明 | error の値 |
data の値 |
---|---|---|---|
none (デフォルト) |
エラーのみ表示 | error.graphQLErrors にエラーを設定 |
undefined |
ignore |
エラーが起きてないように振る舞う | undefined |
部分的なデータが設定 |
all |
部分的なデータとエラーの両方をレンダリングできる | error.graphQLErrors にエラーを設定 |
部分的なデータを設定 |
// '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を参照してください。