🚥

【React】urqlでGraphQLのextensionsに設定したエラー項目を取得する際の実装

に公開

概要

GraphQLクライアントのライブラリ「urql」でエラーの中身をハンドリングする際、urql v3.0.1 ドキュメント日本語訳 Errors に概要がまとめられています。
GraphQLのextensionsにあるエラー項目を取得する場合、CombinedErrorのクラスを使用します。今回はその実装を試してみたのでメモ書きします。

前提

  • 使用したurqlのバージョンは4.2.2です。

実装サンプル

GraphQLのサーバーからは、以下のようにエラーを返すこととします。extensionsにcodeの項目を入れて、このエラーコードを取得します。

{
    "errors": [
        {
            "message": "Dupilicate Id",
            "path": [
                "createUserAccount"
            ],
            "extensions": {
                "code": 403
            }
        }
    ],
    "data": {
        "createUserAccount": null
    }
}

以下のようにCombinedErrorから、extensionsのcode項目を取得する関数を実装します。

// urqlのgraphqlエラーからコードを取得
const getErrorCodeFromGraphQLError = (error: CombinedError): number => {
  // graphqlErrorsの配列が空の場合は500固定(networkErrorと判断)
  if (error.graphQLErrors.length === 0) {
    return 500;
  }
  // エラーの配列の一つ目にエラーコードが入る前提
  return error.graphQLErrors[0].extensions.code as number;
};

以下のように呼び出し元で、上記の関数を使用してエラーコード判定をします。(該当部分だけ抜粋して記載)

const [createUserAccountMutationResult, createUserAccountMutation] = useCreateUserAccountMutation();

const submitRegisterUser = async (submitValues: UserAccountSubmitValues) => {
  const result = await createUserAccountMutation({user: submitValues});
  // エラーの場合
  if (result.error) {
    // 結果のerrorsからextensionsのエラーコードを取得
    const errorCode = getErrorCodeFromGraphQLError(result.error);
    // エラーコードによってメッセージを変える
    notifications.show({
      id: "submitRegister-error",
      position: "top-center",
      withCloseButton: true,
      autoClose: 5000,
      title: "会員登録エラー",
      message:
        errorCode == 400
          ? "入力内容に不備があります。再度入力の上登録お願いします。"
          : errorCode == 403
          ? "登録済みのアカウントです。ログインから認証してください。"
          : "会員登録でエラーが起きました。",
       color: "red",
       loading: false,
    });
  } else {
    notifications.show({
      id: "submitRegister-success",
      position: "top-center",
      withCloseButton: true,
      autoClose: 5000,
      title: "会員登録",
      message: "会員登録しました。",
      color: "green",
      loading: false,
    });
  }
};

Discussion