🦆

【React】Apollo Client 4.0でのgraphql-codegen/typescript-react-apolloの対応

に公開

概要

2025年8月にApollo Clientが4.0にメジャーバージョンアップされました。大きな変更点の一つとしてはモジュールのimport部分で、MigrationガイドのCodemodへ記載のある通り、useQuery等のhooksのimportが変更されています。
ただ、graphql codegenでhooksを生成する方法、および少し詰まった点で紹介されているような方法でgraphql codegenでhooksを生成すると、この生成されたコードのimport部分が4.0に対応されてません。
graphql-codegen/typescript-react-apolloのページを確認すると2025年9月時点ではApollo Client 4.0に対応しておらず、「client preset」への移行を案内していることから、hooksの生成からclient presetへの移行が必要な感じです。(今後も対応されない雰囲気を感じるので)

client presetの詳細についてはGraphQL Code Generator v3 Roadmapで推されているclient-presetを紹介するを参照頂くとして、取り急ぎclient presetへの移行についてメモ書きします。

前提

  • 使用したapollo/clientのバージョンは4.0.5です。
  • 使用したgraphql-codegen/cliのバージョンは6.0.0です。
  • 使用したgraphql-codegen/client-presetのバージョンは5.0.1です。

client presetへの移行での修正箇所など

まず、package.jsonですが、「@graphql-codegen/cli」と「@graphql-codegen/client-preset」があれば最低限動作するはずです。introspectionはお好みで。

package.json
"devDependencies": {
  "@graphql-codegen/cli": "^6.0.0",
  "@graphql-codegen/client-preset": "^5.0.1",
  "@graphql-codegen/introspection": "^5.0.0",
}

次にcodegen.jsのgenerates部分です。変更前は以下のようにtypescript-react-apolloを使用した形にしていますが、

codegen.js(変更前)
generates: {
  "./src/graphql/gen/graphql.tsx": {
    plugins: [
      "typescript",
      "typescript-operations",
      "typescript-react-apollo",
    ],
    config: {
      skipTypename: false,
      withHooks: true,
      withHOC: false,
      withComponent: false,
      noExport: false,
      wrapFieldDefinitions: true,
      useTypeImports: true,
     },
}

以下の通りclient presetを使用するようにします。

codegen.js(変更後)
generates: {
  "./src/graphql/gen/": {
    preset: "client",
    config: {
      useTypeImports: true,
      skipTypename: false,
      withHooks: true,
      documentMode: "documentNode",
    },
  },
}

クエリの定義は変更不要で以下のようなものを用意して、

query.ts
import { gql } from "@apollo/client/core";

export const getMyNovelsQuery = gql`
  query GetMyNovels {
    getMyNovels {
      id
      title
      description
    }
  }
`;

export const addNovelMutation = gql`
  mutation AddNovel($title: String!, $description: String) {
    addNovel(title: $title, description: $description)
  }
`;

generateするとgraphql.tsへ、以下のようなクエリのドキュメントが生成されます。

graphql.ts
export const GetMyNovelsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMyNovels"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getMyNovels"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]}}]} as unknown as DocumentNode<GetMyNovelsQuery, GetMyNovelsQueryVariables>;

あとは、このドキュメントを使用してクエリの呼び出しを修正していきます。以下のように生成したhooksを呼び出してた箇所を、

SampkeComponets.ts(変更前)
const { data, error, loading, refetch } = useGetMyNovelsQuery({
  fetchPolicy: "network-only",
});
const [addNovel, { loading: addNovelLoading }] = useAddNovelMutation();

useQueryとuseMutationを用いて、以下の通りドキュメントを読み込ませるように修正します。

SampkeComponets.ts(変更後)
const { data, error, loading, refetch } = useQuery(GetMyNovelsDocument, {
  fetchPolicy: "network-only",
});
const [addNovel, { loading: addNovelLoading }] = useMutation(AddNovelDocument);

Discussion