DEV Community

JP Calvo
JP Calvo

Posted on

Automating GraphQL Code Generation in React Query (NextJS)

When working with GraphQL APIs, developers often encounter repetitive tasks such as writing boilerplate code for queries, mutations, and types. Manually managing these tasks not only consumes valuable development time but also increases the risk of introducing errors and inconsistencies.

To address this challenge, we can leverage the power of GraphQL Codegen along with React Query to automate code generation and streamline the integration between GraphQL and React applications. In this article, we will explore how to set up and use GraphQL Codegen with React Query in a Next.js project to automate the generation of hooks and types based on your GraphQL schema.

The Problem: Manual Code Generation

Developers working with GraphQL APIs often find themselves in a situation where they need to manually write repetitive code for queries, mutations, and types. This manual process is time-consuming, error-prone, and can lead to inconsistencies between the frontend and backend codebases. It becomes increasingly challenging to keep the frontend code in sync with the server schema as the project grows in complexity.

The Solution: GraphQL Codegen and React Query

To automate code generation and eliminate the manual effort involved in creating GraphQL-related code, we can utilize a powerful tool called GraphQL Codegen. GraphQL Codegen allows us to automatically generate TypeScript types, hooks, and other utilities based on our GraphQL schema.

When combined with React Query, a popular data-fetching library for React applications, we can further enhance our development workflow. React Query simplifies data fetching, caching, and state management, providing a seamless integration with GraphQL Codegen-generated code. This combination ensures type safety, improves developer productivity, and reduces the likelihood of errors.

In the following sections, we will walk through the installation process, configuration setup, and demonstrate how to generate code based on our GraphQL schema. By the end of this article, you will have a clear understanding of how to harness the power of GraphQL Codegen and React Query to automate code generation and improve your GraphQL development experience.

Prerequisites

Before we begin, make sure you have the following installed on your system:

  • node.js (version 14 or higher)
  • a package manager like npm

Installation

To get started, we need to set up a new Next.js project. Open your terminal and run the following command:

npx create-next-app@latest myapp --use-npm --ts
Enter fullscreen mode Exit fullscreen mode

This command will scaffold a new Next.js project using npm as the package manager. Feel free to replace myapp with the desired name of your project.

Once the project is created, navigate to the project directory:

cd myapp
Enter fullscreen mode Exit fullscreen mode

Now, let's install the required dependencies:

npm install @tanstack/react-query graphql graphql-request
Enter fullscreen mode Exit fullscreen mode

Next, we need to install the following packages as dev dependencies:

npm install --save-dev dotenv graphql-config @graphql-codegen/cli @graphql-codegen/add @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-query
Enter fullscreen mode Exit fullscreen mode

Configuring GraphQL Codegen

First, we need to create a .env file at the root of our project and define the API URL. For demonstration purposes, we will use the countries API. Open the .env file and add the following line:

NEXT_PUBLIC_COUNTRIES_API=https://countries.trevorblades.com/
Enter fullscreen mode Exit fullscreen mode

Next, let's create a configuration file for GraphQL Codegen. Create a new file named .graphql.ts at the root of your project. Note that we are deviating from the recommended codegen.yml naming convention to enable integration with the VSCode extension, which supports specific file name formats such as .graphql.ts. This enables autocompletion and provides a more enhanced development experience.

Inside the .graphql.ts file, paste the following code:

import dotenv from "dotenv";
import { IGraphQLConfig } from "graphql-config";

dotenv.config({
  debug: true,
  path: ".env",
});

const config: IGraphQLConfig = {
  schema: [process.env.NEXT_PUBLIC_COUNTRIES_API!],
  documents: ["src/graphql/**/*.gql"],
  extensions: {
    codegen: {
      debug: true,
      verbose: true,
      ignoreNoDocuments: true,
      overwrite: true,
      hooks: {
        afterAllFileWrite: ["prettier --write"],
      },
      generates: {
        "src/__generated__/index.ts": {
          plugins: [
            "typescript",
            "typescript-operations",
            "typescript-react-query",
            {
              add: {
                content: "/* eslint-disable */\n// @ts-nocheck\n",
              },
            },
          ],
          config: {
            addDocBlocks: false,
            dedupeFragments: true,
            pureMagicComment: true,
            disableDescriptions: true,
            fetcher: "graphql-request",
            legacyMode: false,
            exposeFetcher: true,
            exposeDocument: true,
            exposeQueryKeys: true,
            exposeMutationKeys: true,
            addInfiniteQuery: true,
            errorType: "any",
          },
        },
      },
    },
  },
};

export default config;
Enter fullscreen mode Exit fullscreen mode

This configuration file specifies the schema location, document paths, code generation options, and output file paths. It also defines the plugins to be used, such as TypeScript, TypeScript Operations, and TypeScript React Query.

Integrating React Query and GraphQL Request

Let's create our config file first. Create a file named config.ts just under src/app and add the following lines:

import { QueryClient } from "@tanstack/react-query";
import { GraphQLClient } from "graphql-request";

export const queryClient = new QueryClient();
export const graphqlClient = new GraphQLClient(
  process.env.NEXT_PUBLIC_COUNTRIES_API as string,
);
Enter fullscreen mode Exit fullscreen mode

Now, create a file called AppProvider.tsx in src/app directory and paste the following code into the file:

"use client";

import { QueryClientProvider } from "@tanstack/react-query";
import { PropsWithChildren } from "react";
import { queryClient } from "./config";

export function AppProvider({ children }: PropsWithChildren) {
  return (
    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Next, open the src/app/layout.tsx file and replace its contents with the following code:

import { Metadata } from "next";
import { Inter } from "next/font/google";
import { PropsWithChildren } from "react";
import { AppProvider } from "./AppProvider";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({ children }: PropsWithChildren) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <AppProvider>{children}</AppProvider>
      </body>
    </html>
  );
}
Enter fullscreen mode Exit fullscreen mode

Creating GraphQL Queries/Mutations and Generating Code with GraphQL Codegen

To demonstrate how to create GraphQL queries and mutations, let's start by creating a basic query. Inside the src/graphql directory, create a file named queries.gql and paste the following code:

query Countries($filter: CountryFilterInput) {
  countries(filter: $filter) {
    code
    name
  }
}
Enter fullscreen mode Exit fullscreen mode

You should get autocompletion in VSCode, if not, please restart your editor.

Now, the last step is to run the command below to generate our hooks and types:

graphql-codegen --config .graphql.ts
Enter fullscreen mode Exit fullscreen mode

If the operation is successful, you should see a new file named index.ts inside the src/__generated__ directory. This file contains all the generated types and hooks, ready to be imported and used in your components.

Here's an example of how you can use the generated hook:

// src/app/Countries.tsx
"use client";

import { useCountriesQuery } from "@/__generated__";
import { graphqlClient } from "./config";

export function Countries() {
  const { data, isLoading } = useCountriesQuery(graphqlClient, {
    filter: {
      code: {
        eq: "PH",
      },
    },
  });

  return (
    <div>
      {isLoading && <p>Loading...</p>}

      <ul>
        {data?.countries.map(({ code, name }) => (
          <li key={code}>{name}</li>
        ))}
      </ul>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

To access query keys, you can use the useCountriesQuery.getKey function like so

useCountriesQuery.document;
Enter fullscreen mode Exit fullscreen mode

If you want to prefetch queries for example in getStaticProps, you can use the following example:

import { CountryFilterInput, useCountriesQuery } from "@/__generated__";
import { graphqlClient, queryClient } from "./config";

export async function getStaticProps() {
  const filter: CountryFilterInput = {
    code: {
      eq: "PH",
    },
  };

  await queryClient.prefetchQuery({
    queryKey: useCountriesQuery.getKey({ filter }),
    queryFn() {
      return useCountriesQuery.fetcher(graphqlClient, { filter });
    },
  });

  return {
    props: {
      dehydratedState: dehydrate(queryClient),
    },
  };
}
Enter fullscreen mode Exit fullscreen mode

These updates demonstrate how to use the generated hook, access query keys and the document node, and prefetch queries using getStaticProps in Next.js.

Let me know if there's anything else I can help you with!

Conclusion

In this article, we explored the process of automating GraphQL code generation with React Query in a Next.js project. By using GraphQL Codegen, we can automatically generate TypeScript types and hooks based on our GraphQL schema. The integration with React Query simplifies data fetching and state management, improving development efficiency and reducing the likelihood of errors.

By following the installation steps, configuring GraphQL Codegen, and leveraging React Query, you can streamline your GraphQL development workflow and enhance your productivity. Feel free to experiment with different queries, mutations, and code generation options to suit your project's needs.

Happy coding!

References

  • VSCode GraphQL Extension: A Visual Studio Code extension that provides GraphQL syntax highlighting, autocomplete, and other helpful features.
  • GraphQL Codegen: A tool that generates code based on your GraphQL schema and queries, reducing the amount of manual work required.
  • React Query: A powerful data-fetching library for React applications that simplifies API fetching, caching, and state management.
  • Next.js: A popular React framework for building server-rendered and statically generated web applications.
  • GraphQL: A query language for APIs that provides a flexible and efficient approach to data fetching and manipulation.

Top comments (1)

Collapse
 
glvnzn profile image
glvnzn

thanks for sharing!