Generating types and react-query hooks from a graphql schema.
Graphql codegen is a great tool; zeus-graphql is a neat lib. But they don't exactly fit what I want 😿
So here we go, I just figured I'd do something for giggles 🤷.
To install, use either pnpm, yarn or npm:
yarn add -D graphql-codegen-react-queryLet's setup our codegen tooling by running the codegen-init command:
yarn codegen-initThis command takes three optional parameters:
| Parameter | Description | Default value |
|---|---|---|
| c | Where to write the codegen config file | . (current folder) |
| o | Where generated code should be written | ./api |
| u | Graphql api url. If it doesn't start with http, the variable will be treated as an environment variable name | http://localhost:3333/graphql |
So if I need to use custom params, I'd do:
yarn gqlCodegen-init -c ./libs/graphql/codegen/src -o libs/graphql/artifacts/src/api -u NEXT_PUBLIC_GQL_API_URL🗯️ This command generates two files:
- The
react-query.codegen.ymlconfig file.- The fetcher hook. You might need to inject config in the fetching logic, like setting an
Authorizationheader for example; that is why the fetching logic is externalized in this hook.
The config file typically looks like this:
# Where generate code should be writtenoutputPath: 'libs/graphql/artifacts/src/api/codegen'# The environment variable name containing the url to the graphql schema (or directly said url)schemaUrl: NEXT_PUBLIC_GQL_API_URL# Fetcher hook configfetcher:
# Path to the fetcher, relative to the generated queries/mutationspath: './../../useFetchData'# fetcher hook name (expecting a named export)functionName: 'useFetchData'# Queries that should be generated as infinite queries with react-queryinfiniteQueries:
- useProductsByPage🚨 Make sure introspection is enabled on the backend you target
Generating types from a graphql schema is easy enough using cli. Usage is as follows:
gqlCodegen -c [configFilePath]
Options:
--help Show help [boolean]
--version Show version number [boolean]
-c Codegen config file path
[required] [default: "./react-query.codegen.yml"]
Examples:
gqlCodegen -c ./libs/graphql/react-query.codegen.yml
With that in mind, we can add a script to our package.json:
{
[...],
"scripts:" {
"codegen": "gqlCodegen -c ./libs/graphql/react-query.codegen.yml",
[...]
}
}From a schema like this...
enumGqlOrderedItemStatus {
preparing readyToBeSent shippingInProgress shipped
}
typeGqlOrderedItem {
id: ID!quantity: Int!name: String!image: Stringprice: Float!status: GqlOrderedItemStatus!
}
typeGqlOrder {
id: ID!idUser: ID!idCreditCard: ID!createdAt: DateTime!creditCardNumber: String!items: [GqlOrderedItem!]!
}I expect to get this:
exporttypeGqlOrderedItemStatus='preparing'|'readyToBeSent'|'shippingInProgress'|'shipped'exportinterfaceGqlOrderedItem{id: string;quantity: number;name: string;image?: string;price: number;status: GqlOrderedItemStatus}exportinterfaceGqlOrder{id: string;idUser: string;idCreditCard: string;createdAt: Date;creditCardNumber: string;items: Array<GqlOrderedItem>;}It would be great if I could use named query hooks (one react hook by graphql query) but still be able to select what I want in the result 🤔
For example, for a schema like this, I should have a named query hook useCategoriesQuery with type inference:
typeGqlProduct {
id: ID!idCategory: ID!name: String!description: String!image: String!price: Float!stock: Int!
}
typeGqlCategoryWithProducts {
id: ID!name: String!products: [GqlProduct!]
}
typeQuery {
categories: [GqlCategoryWithProducts!]!
}If i want the entire query result, I can use useCategoriesQuery instead of useCategoriesPartialQuery:
It would be neat if I could get the results from several graphql queries by calling one single react hook 🤔
Let's use the useGqlQuery hook that does just that:
I would be nice if I had strong typings for arguments and results 🤔
It would be awesome if I could still easily tweak react query hooks 🤔





