1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

graphql codegenでhooksを生成する方法、および少し詰まった点

Posted at

行き詰まった経緯

graphqlの練習としてフロントエンドでcodegenを使用して自動的にコード生成をしようとしていた。

以前も使用したことはあったので多少は設定に困らなかったが、今回はhooksも自動生成しようと思って、設定内容を変えてみた。
実装の概略は次章で説明する。
問題となったエラーは以下の通り
the name `GetUsersDocument` is defined multiple times

実装

codegenをinstall

pnpm i -D graphql @graphql-codegen/cli

codegenの初期化
pnpm grapql-codegen init

対話形式で初期化が始まる(今回はNextjsのプロジェクトであるためReactを選択)

? What type of application are you building? (Use arrow keys)
  Backend - API or server 
  Application built with Angular 
❯ Application built with React 
  Application built with Stencil 
  Application built with Vue 
  Application using graphql-request 
  Application built with other framework or vanilla JS 

schemaの場所の指定(今回はlocalhost:8080にgraphqlサーバーが立っている)

? Where is your schema?: (path or url) http://localhost:8080/v1/graphql

graphqlドキュメントを読み込むパスの指定

? Where are your operations and fragments?:src/graphql/**/*.graphql

生成されたコードをどこに出力するかの設定(今回はsrc/generates/)

? Where to write the output: src/generates/

introspection fileを作るかどうか (今回はyes)

? Do you want to generate an introspection file? (y/N) 

コンフィグファイルの名前(今回はデフォルト)

? How to name the config file? (codegen.ts) 

npmコマンドの名前(これもデフォルト)

? What script in package.json should run the codegen? (codegen) 

対話終了

Fetching latest versions of selected plugins...

    Config file generated at codegen.ts

      $ npm install

    To install the plugins.

      $ npm run codegen

    To run GraphQL Code Generator.

npm installをしてねって言われてるので
pnpm installを実行

試しにクエリドキュメント作成

src/graphql/query/getUser.graphql
query GetUsers {
    users {
        id
        userName
    }
}

データベースにはiduserNameのcolumnを持つusersテーブル

codegenを実行するときは
npm run codegenを使ってねって言われてるので
pnpm codegenを実行

構造は以下の通り

src
├── generates
│   ├── fragment-masking.ts
│   ├── gql.ts
│   ├── graphql.ts
│   └── index.ts
├── graphql
│   └── query
│       └── getUser.graphql

ここまでで単純なgraphqlのコード生成は終了

本題

今回の目標はhooksを生成すること

必要なライブラリをインストール
npm i -D @graphql-codegen/typescript @graphql-codegen/typescript-react-apollo @graphql-codegen/typescript-operations @apollo/client

codegen.tsを次のように編集

./codegen.ts
import type { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
    overwrite: true,
    schema: "http://localhost:8080/v1/graphql",
    documents: "src/graphql/**/*.graphql",
    generates: {
        "src/generates/": {
            preset: "client",
            plugins: [
                "typescript",
                "typescript-operations",
                "typescript-react-apollo",
            ],
            config: {
                skipTypename: false,
                withHOC: true,
                withComponent: false,
                scalars: {
                    uniqueidentifier: "string",
                },
            },
        },
        "./graphql.schema.json": {
            plugins: ["introspection"],
        },
    },
};

export default config;

pluginsで使用するpluginを設定

configで生成されるコードの詳細を設定できる

諸々を省くが実際にクエリを叩いたところ以下エラーが出力された

./src/generates/graphql.ts
NonErrorEmittedError: (Emitted value instead of an instance of Error) 
  x the name `GetUsersDocument` is defined multiple times

エラーの内容としてはgraphql.tsファイル内でGetUserDocumentが複数宣言されていることだった

codegen.tsを以下のように編集するとエラーは改善された

./codegen.ts
generates: {
        "src/generates/graphql.ts": { //出力先の変更
                            //presetを削除
            plugins: [
                "typescript",
                "typescript-operations",
                "typescript-react-apollo",
            ],
            config: {
                skipTypename: false,
                withHOC: false,
                withComponent: false,//出力するファイルを一つに設定する
                scalars: {
                    uniqueidentifier: "string",
                },
            },
        },
        "./graphql.schema.json": {
            plugins: ["introspection"],
        },
    },

どうやらpreset:"client"が悪さをしていたみたい

そもそもpresetとはなんなのか

公式ドキュメントによると
generates.preset - A list of presets to use for the output. Presets are a way to dynamically create the list of output files based on the input schema. near-operation-file-preset is a good example
とされている

codegenで生成されるコードとpresetで生成されたコードが重複してエラーが出力されていた感じなのだろうか(ちゃんと理解できてない分野であるため下手なことが言えない)

hooksを出力するメリット

なぜ今回出力先をhooksにしたのかについて
withHooks:trueにせずにデフォルトで使用する場合データを取得するクエリは以下のように書く必要がある(本記事ではcodegenを主に取り扱っているためapollo clientに関して説明はしない)

hoge.tsx
const getUsersDoc = gql`
    query GetUsers {
        users {
            id
            userName
        }
    }
`
const {data} = useQuery(getUserDoc)

しかし設定を適用すると

/graphql/query/getUser.graphql
query GetUsers {
    users {
        id
        userName
    }
}
hoge.tsx
    const { data } = useGetUsersQuery();

といった感じでクエリと関数を別ファイルに分けることができる上に関数の命名がドキュメントに基づいた名前になるため直感的にわかりやすいと感じた。
hooks出力にしなくてもドキュメントは別ファイルに分けることはできると言われればそれはそうとしか返せない。
関数名が変わるのが私個人としてはわかりやすくていいかなあといった感じだった。
そこもドキュメントの名前見ればわかるだろうと言われればそれもそうなのかもしれない

その他ここは違うなどの意見がございましたら教えていただけると幸いです。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?