Docs
Guides
React

Guide: React and GraphQL

GraphQL Code Generator provides typed code generation for React Query, URQL React, React Apollo Client, and other clients.

The plugins and available options vary depending on the target client; for this reason, you find guides for each of them below:

All the following guides query the schema below:

type Author {
  id: Int!
  firstName: String!
  lastName: String!
  posts(findTitle: String): [Post]
}
 
type Post {
  id: Int!
  title: String!
  author: Author
}
 
type Query {
  posts: [Post]
}

React Query

Most React Query usage with GraphQL and TypeScript will look as follows:

import { useQuery } from '@tanstack/react-query'
import { request, gql } from 'graphql-request'
 
interface PostQuery {
  posts: {
    id: string
    title: string
    author?: {
      id: string
      firstName: string
      lastName: string
    }
  }[]
}
 
const postsQueryDocument = gql`
  query Posts {
    posts {
      id
      title
      author {
        id
        firstName
        lastName
      }
    }
  }
`
 
const Posts = () => {
  const { data } = useQuery<PostQuery>('posts', async () => {
    const { posts } = await request(endpoint, postsQueryDocument)
    return posts
  })
 
  // …
}

Not typing or manually maintaining the data-types can lead to many issues:

  • outdated typing (regarding the current Schema)

  • typos

  • partial typing of data (not all Schema's fields has a corresponding type)

For this reason, GraphQL Code Generator provides a @graphql-codegen/typescript-react-query plugin that generates a typed hook for each GraphQL operation.

Just a few configuration steps are required to get those typed hooks generated:

1. Install the @graphql-codegen/typescript-react-query plugin

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

2. Configure the plugin

Create or update your codegen.yaml file as follows:

schema: http://my-graphql-api.com/graphql
documents: './src/**/*.tsx'
generates:
  ./graphql/generated.ts:
    plugins:
      - typescript
      - typescript-operations
      - typescript-react-query
    config:
      fetcher: fetch
💡

schema and documents values

schema needs to be your target GraphQL API URL ("/graphql" included).

documents is a glob expression to your .graphql, .ts or .tsx files.

3. Run the codegen and update your code

Assuming that, as recommended, your package.json has the following script:

{
  "scripts": {
    "generate": "graphql-codegen"
  }
}

Running the following will generate the graphql/generated.tsx file.

yarn generate

We can now update our code as follows:

import gql from 'graphql-tag'
import { useQuery } from '@tanstack/react-query'
import { usePosts } from '../graphql/generated'
 
gql`
  query Posts {
    posts {
      id
      title
      author {
        id
        firstName
        lastName
      }
    }
  }
`
 
const Posts = () => {
  const { data } = usePosts()
 
  // `data` is typed!
  // …
}

For more advanced configuration (custom fetcher, infinite queries), please refer to the plugin documentation.

For a different organization of the generated files, please refer to the "Generated files colocation" page.

Apollo and URQL

Optimal configuration for Apollo and URQL

While Apollo and URQL have their GraphQL Code Generator plugins that generate fully-typed hooks, they are also compatible with a plugin named @graphql-codegen/typed-document-node.

@graphql-codegen/typed-document-node plugin provides the best Developer Experience for Apollo and URQL:

  • low bundle impact (compared to other plugins)
  • better backward compatibility (easier to migrate to)
  • more flexible

Given the following code example:

import { gql, useQuery } from '@apollo/client'
 
interface PostQuery {
  posts: {
    id: string
    title: string
    author?: {
      id: string
      firstName: string
      lastName: string
    }
  }[]
}
 
const postsQueryDocument = gql`
  query Posts {
    posts {
      id
      title
      author {
        id
        firstName
        lastName
      }
    }
  }
`
 
const Posts = () => {
  const { data } = useQuery<PostQuery>(postsQueryDocument)
 
  // …
}

installing and configuring the @graphql-codegen/typed-document-node plugin would allow the following refactoring:

import { useQuery } from '@apollo/client'
import { postsQueryDocument } from './graphql/generated'
 
const Posts = () => {
  const { data } = useQuery(postsQueryDocument)
 
  // `result` is fully typed!
  // …
}

Just a few configuration steps are required to get those typed document nodes generated:

1. Move all your GraphQL documents in dedicated .graphql files

To have @graphql-codegen/typed-document-node working and avoid code duplication, we highly recommend moving all gql document declarations outside of .tsx/.ts files. For this, create a colocated .graphql file for each GraphQL document, as follows:

# 'Document' will be appended to the name of the query in the generated output
query postsQuery {
  posts {
    id
    title
    author {
      id
      firstName
      lastName
    }
  }
}

2. Install the @graphql-codegen/typed-document-node plugin

yarn add -D @graphql-codegen/typed-document-node @graphql-codegen/typescript @graphql-codegen/typescript-operations

3. Configure the plugin

Create or update your codegen.yaml file as follows:

schema: http://my-graphql-api.com/graphql
documents: './src/**/*.graphql'
generates:
  ./src/generated.ts:
    plugins:
      - typescript
      - typescript-operations
      - typed-document-node
💡

schema and documents values

schema needs to be your target GraphQL API URL ("/graphql" included).

documents is a glob expression to your .graphql files.

4. Run the codegen and update your code

Assuming that, as recommended, your package.json has the following script:

{
  "scripts": {
    "generate": "graphql-codegen"
  }
}

Running the following generates the graphql/generated.tsx file.

yarn generate

We can now update our code as follows:

import { useQuery } from '@apollo/client'
import { postsQueryDocument } from './graphql/generated'
 
const Posts = () => {
  const { data } = useQuery<PostQuery>(postsQueryDocument)
 
  // `result` is fully typed!
  // …
}

For more advanced configuration, please refer to the plugin documentation.

If you are curious about @graphql-codegen/typed-document-node inner workings, feel free to read the following The Guild's CTO blog post: TypedDocumentNode: the next generation of GraphQL and TypeScript.

Typed hooks for Apollo and URQL

GraphQL Code Generator also proposes two plugins (one for Apollo one for URQL) that generate fully-typed hooks.

Given the following code example:

import { gql, useQuery } from '@apollo/client'
 
interface PostQuery {
  posts: {
    id: string
    title: string
    author?: {
      id: string
      firstName: string
      lastName: string
    }
  }[]
}
 
const postsQueryDocument = gql`
  query Posts {
    posts {
      id
      title
      author {
        id
        firstName
        lastName
      }
    }
  }
`
 
const Posts = () => {
  const { data } = useQuery<PostQuery>(postsQueryDocument)
 
  // …
}

installing and configuring the @graphql-codegen/typescript-react-apollo or @graphql-codegen/typescript-urql plugin would allow the following refactoring:

import { usePostsQuery } from './graphql/generated'
 
const Posts = () => {
  const { data } = usePostsQuery()
 
  // `result` is fully typed!
  // …
}

Some might prefer this approach to @graphql-codegen/typed-document-node since its results in a total abstraction of the query logic and fewer imports.

However, keep in mind that hooks generation results in:

  • greater bundle size
  • an increase of the number of specific hooks in the given application

Just a few configuration steps are required to get those typed hooks generated:

1. Install the @graphql-codegen/typescript-react-apollo or @graphql-codegen/typescript-urql plugin

For React Apollo:

yarn add -D @graphql-codegen/typescript-react-apollo @graphql-codegen/typescript @graphql-codegen/typescript-operations

For URQL React:

yarn add -D @graphql-codegen/typescript-urql @graphql-codegen/typescript @graphql-codegen/typescript-operations

2. Configure the plugin

Create or update your codegen.yaml file as follows:

schema: http://my-graphql-api.com/graphql
documents: './src/**/*.tsx'
generates:
  graphql/generated.ts:
    plugins:
      - typescript
      - typescript-operations
      - typescript-react-apollo
    config:
      withHooks: true
💡

schema and documents values

schema needs to be your target GraphQL API URL ("/graphql" included).

documents is a glob expression to your .graphql, .ts or .tsx files.

3. Run the codegen and update your code

Assuming that, as recommended, your package.json has the following script:

{
  "scripts": {
    "generate": "graphql-codegen"
  }
}

Running the following generates the graphql/generated.tsx file.

yarn generate

We can now update our code as follows:

import { usePostsQuery } from './graphql/generated'
 
const Posts = () => {
  const { data } = usePostsQuery()
 
  // `result` is fully typed!
  // …
}

For more advanced configuration, please refer to the plugin documentation:

For a different organization of the generated files, please refer to the "Generated files colocation" page.