Closed7
@graphql-codegen/client-presetでData fragment maskingを試す
@graphql-codegen/typescript-react-queryプラグインでhookを生成しようと思ったが、ドキュメントを見るとclient-presetを推奨するとあったためこれを試す
We now recommend using the client-preset package for a better developer experience and smaller impact on bundle size.
client-presetが生まれた背景が以下のissueに書いてある
既存の各種プラグイン(typescript-react-apollo、typescript-react-queryなど)はGraphQLクライアントをタイプセーフな方法でラップするフックやSDKの生成している。
これには以下の課題がある。
- バンドルサイズの肥大化
- 生成したフックシグネチャとGraphQLクライアントとのずれ
- パッケージ間での構成オプションとプリセットの互換性の不整合
client-presetはすべてのGraphQLクライアント向けのプリセットで、バンドルサイズの縮小や型の強化が期待される。useQueryには生成したTypeDocumentNodeを渡す。
そしてRelayのようなFragment maskingをするためのAPI(useFragment)まで使える。
サンプルコード
import { FragmentType, useFragment } from './gql/fragment-masking'
import { graphql } from '../src/gql'
export const FilmFragment = graphql(/* GraphQL */ `
fragment FilmItem on Film {
id
title
releaseDate
producers
}
`)
const Film = (props: { film: FragmentType<typeof FilmFragment> }) => {
const film = useFragment(FilmFragment, props.film)
return (
<div>
<h3>{film.title}</h3>
<p>{film.releaseDate}</p>
</div>
)
}
export default Film
graphqlクライアントはreact query (with graphql-request)
$ yarn add graphql react-query graphql-request
$ yarn add -D @graphql-codegen/cli @graphql-codegen/client-preset
// package.json
"scripts": {
"codegen": "graphql-codegen --config codegen.ts"
},
$ yarn codegen
src/gql配下にコードが生成される
- fragment-masking.ts
- その名の通り。FragmentType型やuseFragmentが生成される
- gql.ts
- ここにTypedDocumentNodeが吐かれる。この段階ではまだない。
- graphql.ts
- ここにgraphqlスキーマから生成された型が吐かれる
- index.ts
- gql.tsとfragment-masking.tsを再エクスポートしてる
typescript-react-queryが生成するようなフックは生成されない
src/gql/gql.tsのgraphql関数を使ってGraphQLクエリやミューテーションを定義する
# Parent Component
const allFilmsWithVariablesQueryDocument = graphql(/* GraphQL */ `
query allFilmsWithVariablesQuery($first: Int!) {
allFilms(first: $first) {
edges {
node {
...FilmItem
}
}
}
}
`)
# child component
export const FilmFragment = graphql(/* GraphQL */ `
fragment FilmItem on Film {
id
title
releaseDate
producers
}
`)
yarn codegenするとTypeDocumentNodeが生成されている
生成されたallFilmsWithVariablesQueryDocumentをreact-queryのuseQueryに渡す
仮にapolloやurqlに変えた場合でもuseQuery系のメソッドに同じようにDocumentを渡せばいい
# Parent Component
const { data } = useQuery(
['films'],
async () =>
await request(
'https://swapi-graphql.netlify.app/.netlify/functions/index',
allFilmsWithVariablesQueryDocument,
{
first: 10,
}
)
)
このスクラップは2023/04/28にクローズされました