Using GraphQL Code Generator in React

Wynn
4 min readJun 27, 2024

--

Recently, our team adopted GraphQL schema. So, I decided to cover the benefits of using graphql-codegen in this context.

Before We Begin

when developing GraphQL APIs, there are two main methodologies: Code Frist and Schema First

  • Code First: This approach places the Single source of Truth (SSOT) in the code. For example, in NestJS, the backend developer writes business logic with appropriate decorators, and upon successful compilation, the schema is generated based on the compiled source.
  • Schema First: This method involves writing the Schema Definition Language (SDL) first and then generating types from the schema to ensure that the resolver returns responses that match the strict types defined.

Our team uses the Schema First approach. We chose this because it allows frontend and backend developers to discuss the schema in advance, reducing the cost of future changes. Additionally, our frontend team uses MSW (Mock Service Worker) to assist with development and testing, which further leverages the advantages of the Schema First method.

Personally, Schema First allows for pre-designing with business requirements in mind before writing code. It minimize dependency on the code itself, which can be beneficial.

However, this doesn’t mean Code First is bad. For instance, NestJS provides the @nestjs/graphql module, which wraps Appolo Server and offers guides for both Code First and Schema First, although Code First is usually presented first in the documentation.

A notable contributor in the NestJS community prefers the Code First approach. He believes that backend teams can focus solely on the code, leading to better Developer Experience than with Schema First. I agree that developing everything in a familiar programming language can improve productivity. Both approaches have their pros and cons, so choose the one that fits your team’s needs best.

Why Do We Need GraphQL Code Generator?

Both Code First and Schema First approaches ultimately produce a GraphQL schema. But what can we do with it? Is it just for documentation?

Of course not. Just as the JSON format in REST APIs is simple and intuitive, allowing for serialization/deserialization across the various languages, the GraphQL schema is similarly compatible. Its basic types resemble objects, and scalar types are common in many programming languages.

By using GraphQL, we can strictly define the types of data exchanged between the client and server, minimizing runtime errors. Our team uses TypeScript for both the frontend and BFF servers. Many developers prefer TypeScript over JavaScript due to its static analysis capabilities, which catch errors early.

Setting Up GraphQL Code Generator

To generate types with graphql-codegen you first need a configuration file. Here’s how we set it up, along with brief explanations of each setting:

schema: "path/to/schema.graphql" # Specifies where to fetch the GraphQL schema from
documents: "src/**/*.graphql" # Files containing GraphQL queries to be processed
generates:
src/generated/graphql.tsx:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"
  • schema: Specifies where to fetch the GraphQL schema from. It can be a server URL or a file path if managing client and server in a monorepo (e.g., ./typeDefs/*.graphql )
  • documents: indicates where to find the GraphQL query documents.
  • plugins: Lists the plugins to use for generating types.

Refer to the official documentation for more details on configuration options.

Generating Types

With the configuration file in place, run the GraphQL Code Generator CLI to generate the types:

$ graphql-codegen

this command will generate the necessary TypeScript types from the GraphQL schema. You can then use these types in your React components, replacing any manually defined types.

Creating Custom Hooks

Although using the generated types significantly improves type safety, fronten developers might prefer not to write GraphQL queries directly in tsx files. Instead, you can place your queries in .graphql files and have custom hooks generated automatically.

Example post.graphql

query GetPost($id: ID!) {
post(id: $id) {
id
title
content
}
}

Running the codegen command again will generate custom hooks based on these queries, thanks to the writeHooks option, which is enabled by default.

Using Generated Hooks

With custom hooks generated, you can simplify your components by using these hooks directly:

Example post.tsx

import { useGetPostQuery } from './generated/graphql';

const Post = ({ id }) => {
const { data, loading, error } = useGetPostQuery({ variables: { id } });

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

return (
<div>
<h1>{data.post.title}</h1>
<p>{data.post.content}</p>
</div>
);
};

This approach eliminates the need for manualy type annotations, as TypeScript will automatically infer the types from the generated hooks. This reduces the risk of human error and saves time.

Conclusion

Effectively using GraphQL requires overcoming a certain learning curve, especially if you’re accustomed to REST APIs. However, tools like grapql-codegen can significantly ease this transition by automating type generation, thereby improving developemnt efficiency and reducing errors.

Although GraphQL is not yet as widely adopted in some regions, its benefits make it worth considering for projects where strict type safety and efficient data fetching are critical.

Thank you for reading this long post. I hope it helps you in your GraphQL journey!

--

--