Is the graphql codegen accurately generating the types?

I'm in the process of developing a basic Next.js application with TypeScript by integrating Strapi as a headless CMS.

The main goal is to use Strapi and GraphQL, along with TypeScript, to display content on the Next.js app.

Within Strapi, there is a Color Content type consisting of two colors: red and blue.

GraphQL has been successfully set up in Strapi, and it functions properly in the playground.

query ColorData{
  colors{
    data{
      attributes{
        color_name
      }
    }
  }
}

The output of this query:

{
  "data": {
    "colors": {
      "data": [
        {
          "attributes": {
            "color_name": "Red"
          }
        },
        {
          "attributes": {
            "color_name": "Blue"
          }
        }
      ]
    }
  }
}

In the Next.js app, I am utilizing GraphQL codegen for type generation purposes.

import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  overwrite: true,
  schema: "http://0.0.0.0:1337/graphql",
  documents: "graphql/**/*.ts",
  generates: {
    "./src/__generated__/": {
      preset: "client",
      plugins: []
    }
  }
};

export default config

The generated types related to colors are as follows:

[types here]

However, when attempting to use these types in the Next.js app, they do not seem to correspond correctly with the queried data.

[more code snippets]

If I exclude the types:

<ColorEntityResponseCollection, ColorEntityResponse> 

The console displays data, but with the included types, only the loading indicator appears. What could be causing this issue with the code generation?

Answer №1

The query provided contains incorrect types. Codegen is responsible for generating an output type for each query, which should be used accordingly. This output type only includes the fields specified in the query and matches its structure precisely. In your case, the type would be as follows:

type ColorDataQuery = { 
    colors: { 
        data: [{
            attributes: { 
                color_name: string 
            } 
        }] 
    }
};

It is evident that this type's structure is more deeply nested compared to ColorEntityResponseCollection. Furthermore, there is no field like ColorEntity.id present in this type, unlike in ColorEntityResponseCollection.

Explicitly defining this type is unnecessary since useQuery can automatically infer it based on the query body provided. However, the automation process involves the following steps:

  1. Declare the query body. The declaration may vary depending on the codegen configuration, but in your scenario, the query body should appear as shown below:
import { graphql } from '@/src/__generated__';

const COLOR_DATA = graphql(`
    query ColorData{
      colors{
        data{
          attributes{
            color_name
          }
        }
      }
    }
`);
  1. Execute the codegen command: npx graphql-codegen

  2. Implement the query call using useQuery:

import { COLOR_DATA} from '@/graphql/queries';
import { useQuery } from '@apollo/client';

const Home = () => {
  const {data, loading} = useQuery(COLOR_DATA);
  ...
};

Upon completing these steps, you will observe the IDE highlighting the type corresponding to the query output. https://i.sstatic.net/NUvOW.png

Likely, the IDE will also indicate any differences in field access attempts. The correct way to access fields is demonstrated below:

const Home = () => {
    const {data, loading} = useQuery(COLOR_DATA);

    return (
        <div>
            <ul>
                {data.colors.data.map((color) =>
                    (<li>{color.attributes.color_name}</li>)
                )}
            </ul>
        </div>
    );
}

Read more about TypeScript with Apollo Client in the related article: TypeScript with Apollo Client

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Converting HTML to PDF with rtl support using the JavaScript library jsPDF

I'm attempting to convert HTML to PDF using jsPDF in an Angular 5 project. Below is the code I have so far: import * as jsPDF from "jspdf"; . . . htmlToPdf(){ var doc=new jsPDF(); var specialElementHandlers = { '#content' : function ...

Getting exported members through Typescript Compiler API can be achieved by following these steps:

I am currently working on a project hosted at https://github.com/GooGee/Code-Builder This particular file is being loaded by the Typescript Compiler API: import * as fs from 'fs' Below is a snippet of my code: function getExportList(node: t ...

How to retrieve all query parameters as a single string in a NextJS app router

Although I initially thought this task would be simple, I am actually finding it quite challenging. The specific issue I am facing involves a page with multiple query parameters: /pathname?param1=lorem&param2=ipsum&param3=dolor&param4=sit All ...

Combining Arrays Together in TypeScript

I am in need of a solution to merge two arrays into one using TypeScript. First Array Object: export interface Item{ Label : string, Code : string, Price : number, } Second Array Object: export interface Amou ...

Validation of emails in Angular through the utilization of reactive forms

Hello there, I'm new to Angular and looking for some assistance. Specifically, I am currently working on validating an email input using a reactive form with the keyup event. registerform:any; ngOnInit(): void { this.registerform = new F ...

Insert data into Typeorm even if it already exists

Currently, I am employing a node.js backend in conjunction with nest.js and typeorm for my database operations. My goal is to retrieve a JSON containing a list of objects that I intend to store in a mySQL database. This database undergoes daily updates, bu ...

The Firebase application named `[DEFAULT]` has already been created with conflicting options or configurations

I am currently working on a project using NextJS, NextAuth, and Firebase. During the implementation of NextAuth, I came across this error message: Error - FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists with different op ...

The error message "Next.js encountered an issue with accessing an undefined property 'xx'"

Currently, I am working on developing a straightforward quiz application by utilizing react context and a multi-step form. Below is the snippet of my code responsible for managing form data: import { useState, createContext, useContext } from "react&q ...

The setState function in the useState hook is being called only one time when triggered by an EventListener

Within my functional component, I am utilizing the useState hook to store state. When the user reaches the bottom of the page, I want to dynamically add content. To achieve this, I implemented an EventListener for 'scroll' within a useEffect hook ...

What methods can I use to analyze and determine the sluggish areas within my application?

Running my application locally is smooth and fast, but once deployed on Vercel, things slow down significantly. My app is built with Next.js and uses Prisma as the database client to communicate with an Amazon RDS Postgres instance. Despite being pre-lau ...

The index.ngfactory.ts file threw an unexpected token error, indicating that an appropriate loader may be necessary to handle this specific file

I've spent several hours trying to troubleshoot this persistent error, exhausting all online resources for solutions. The issue arises consistently with every module of Angular Material only during the build process using --env.prod. The webpack confi ...

Spring Boot receiving null values from Angular form submission

I am currently working on a form in Angular that is used to submit information such as author, context, and recently added images. However, I have run into an issue where I am able to successfully retrieve the author and context, but not the images (it alw ...

Why am I getting the "Too many re-renders" error with next.js and useSWR?

As I venture into the world of React and navigate the territories of Next.js for the first time, I encounter a challenge. Within my project, there exists an input field where a user can search for a city by name from a list of all available cities. After ...

When using getStaticPaths, an error is thrown stating "TypeError: segment.replace is not a function."

I am a beginner when it comes to using Next.js's getStaticPaths and I recently encountered an error that has left me feeling lost. Below is the code I have written (using query from serverless-mysql): export async function getStaticPaths() { cons ...

JSDoc encounters issues when processing *.js files that are produced from *.ts files

I am currently working on creating documentation for a straightforward typescript class: export class Address { /** * @param street { string } - excluding building number * @param city { string } - abbreviations like "LA" are acceptable ...

Having trouble with the .d.ts module for images?

I'm relatively new to Typescript and the only thing that's giving me trouble is the tsconfig.json. My issue revolves around importing images (in Reactjs) and them not being found: client/app/Reports/View.tsx:11:30 - error TS2307: Cannot find mod ...

Troubleshooting: Issue with Dependency Injection functionality in Angular 2 starter project

I’ve encountered a strange error whenever I attempt to inject any dependency TypeError: Cannot set property 'stack' of undefined at NoProviderError.set [as stack] (errors.js:64) at assignAll (zone.js:704) at NoProviderError.ZoneAwareError (zon ...

Encountered an error while running npm run dev on a NextJS application due to an

Upon running the npm run dev command, the next app is displaying an error message: $→mmoLD;%g?wŷ↓▬ovH0a5*ؒl͛Siy☺rO7%L]%∟hk ^ SyntaxError: Invalid or unexpected token at wrapSafe (internal/modules/cjs/loader.js:988:16) at Module._comp ...

Is there a way to activate an event when using # or @ in a text field on React/Next.js?

I'm in the process of starting a new project and I am thinking about how to incorporate this into react/nextjs. I want to create a user selection or hashtag selection dialog around the textarea, but I haven't been able to find any helpful article ...

TypeScript primitive type is a fundamental data type within the

Does TypeScript have a predefined "primitive" type or similar concept? Like type primitive = 'number' | 'boolean' | 'string';. I'm aware I could define it manually, but having it built-in would be neat. ...