Closed9
GraphqlQL Code Generator で react-query の hook を自動生成したい

GraphqlQL Code Generator で react-query の hook を自動生成する方法をメモしていく。

Docs

Install
yarn add @graphql-codegen/typescript-react-query
yarn add @graphql-codegen/typescript
yarn add @graphql-codegen/typescript-operations

Configure
codegen.yaml
schema: path/to/schema
documents: './src/**/*.tsx'
generates:
./graphql/generated.ts:
plugins:
- typescript
- typescript-operations
- typescript-react-query
config:
fetcher: fetch

package.json にコマンド追加
package.json
{
"scripts": {
"generate": "graphql-codegen"
}
}

実行
yarn generate

完了!公式 docs 通りに進めればすぐできる。
詳細な設定はこちらから↓

fetcher について
デフォルトの fetcher の場合、毎回 endpoint url や header 情報など同じようなコードを何度も書かなければならずしんどい。
そこで、custom fetcher を作成し、これらの処理を共通化していく。
custom fetcher を利用
config の fetcher を以下のように設定すればOK。
codegen.yaml
config:
fetcher:
+ func: 'graphql/custom-fetcher#useFetchData'
-
func: 'graphql/custom-fetcher#useFetchData'
=>graphql/custom-fetcher
の file 内から named export されているuseFetchData
を custom fetcher として指定
custom fetcher として hook を利用
codegen.yaml
config:
fetcher:
func: 'graphql/custom-fetcher#useFetchData'
+ isReactHook: true
-
isReactHook: true
=> func で指定した関数が hook である場合はtrue
。この値によって、生成される hook のコードが内部に custom hook を含める形で生成される。false
のまま、custom fetcher を hook で作成してしまうと渡される引数が異なったり、Mutation 時にエラーが起きたりするので注意。
graphql/custom-fetcher.ts
export const useFetchData = <TData, TVariables>(
query: string,
options?: RequestInit['headers']
): ((variables?: TVariables) => Promise<TData>) => {
// it is safe to call React Hooks here.
const { url, headers } = React.useContext(FetchParamsContext)
return async (variables?: TVariables) => {
const res = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...headers,
...(options ?? {})
},
body: JSON.stringify({
query,
variables
})
})
const json = await res.json()
if (json.errors) {
const { message } = json.errors[0] || 'Error..'
throw new Error(message)
}
return json.data
}
}
内部で custom hook を利用して context からの値の受け渡しが可能になるので、デフォで "ログイン情報をもとに token を Authorization header に付与する" といった boilerplate になりがちなコードを組み込むことも可能。

Query Key
cache された特定の query data を更新する際に、Query Key が必要になる。
e.g.) Mutation 後に local のデータを更新する
queryClient.setQueryData(myQueryKey, data)
Graphql Code Generator で hooks を自動生成すると、key も自動で生成される。
cache data を更新する際に必要になるので、この自動生成された key を取得できるようにしておくと良い。
exposeQueryKeys: true
を追加
config に exposeQueryKeys: true
に追加すればOK。
codegen.yml
generates:
./src/graphql/generated.ts:
plugins:
- typescript
- typescript-operations
- typescript-react-query
config:
fetcher:
func: '@/graphql/custom-fetcher#useFetchData'
isReactHook: true
+ exposeQueryKeys: true
すると、以下のような key を取得するための関数が hook に生える。
graphql/generated.ts
useUserQuery.getKey = (variables: UserQueryVariables) => ['User', variables];
こんな感じで利用できる↓
const queryKey = useUserQuery.getKey({ id: 'user_id' });
queryClient.setQueryData(queryKey, updatedUser)
このスクラップは2022/06/19にクローズされました