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.

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

Navigating through the directory to locate the referenced folder in a Types

Is there a way to declare a path to a referenced folder in order to have a more concise import statement using the @resources path? I am building from /server by running tsc -b app.ts The following long import statement works: import IEntity from &ap ...

Tips for effectively matching a type definition pattern in TypeScript

Good evening! I'm currently working with Angular and rxjs, but I have a feeling that TypeScript is going to play a significant role in my project today. I've been exploring different methods to achieve my goal, but it's definitely challengi ...

incorrect choice of ngClass

Having sifted through numerous queries, I have come to this realization... The angular [ngClass] is behaving oddly when it comes to values like 10, 24, and 100. I can't seem to figure out the reason behind this behavior. Perhaps someone here might be ...

I am curious about the types of props for the methods within the 'components' object in react-markdown

Having some trouble using 'react-markdown' in NextJs 13 with typescript. TypeScript is showing errors related to the props of the 'code' method, and after searching online, I found a solution that involves importing 'CodeProps&apos ...

Customize time formatting in Angular to accommodate localized time formats

I am utilizing Angular's localization service version 8.3.28 to support English, Spanish (Mexico) with code es-MX, and Spanish (Spain) with code es-SP While using the date pipe: {{ foo.Date | date: 'shortDate' }} The dates are changing to ...

A guide to executing the Prisma seed file within a NextJS environment

If you want to populate your NextJS project's DB with data using a seed.ts file in Prisma, you can do so after running npx prisma migrate dev. To execute this, create your seed.ts file and update your package.json as follows: seed.ts: import logger ...

Is there a way to trigger a request to the backend when the user closes or refreshes the browser?

My Objective: I am working on a lobby feature that updates automatically when a player leaves. Using backend requests and sockets, the lobby is updated to display the current list of players after someone exits. The Challenge: I am faced with the issue ...

What is the reason that Jest is not able to spy on the function?

A custom Hook was developed with only one function being imported. Ensuring this function is called with the correct arguments is crucial. import { IsValueAlreadyRegistered } from "../../entities/registration/actions"; export const useForgetPass ...

cleaner urls using nextjs routing

Currently working on developing a fresh marketing platform for my company utilizing next.js, and encountering some hurdles with URLs. Essentially, I've created a custom API route to retrieve data from our internal database using Prisma: getAllDealers ...

Delaying NextJS useLayoutEffect for an asynchronous function is not recommended

Upon page reload (F5), I need to verify if the user is logged in. In order to achieve this, I utilize the useLayoutEffect hook within the _app.tsx file: const { authenticated, setAuthenticated } = useContext(AuthContext) const fetchRefresh = async () ...

Error encountered with structured array of objects in React Typescript

What is the reason for typescript warning me about this specific line of code? <TimeSlots hours={[{ dayIndex: 1, day: 'monday', }]}/> Can you please explain how I can define a type in JSX? ...

Error: Unable to access _rawValidators property of null object

I'm currently facing an issue with formgroup and formcontrol in Angular. When I run ng serve, it's showing an error in the console. Does anyone have a solution for this? TypeError: Cannot read properties of null (reading '_rawValidators&a ...

Events bound to JSX elements created in an array map are not being triggered by React

My current task involves working on a compact react + typescript (1.6) application designed for editing slideshows. The functionality of the app is straightforward. A sidebar on the left displays all existing slides, and upon clicking, a canvas appears on ...

When I try to start the editor with HTML content using the convertFromHTML method, I encounter an error stating that

I am encountering an error when trying to initialize my Editor state with a HTML markup. at renderToString (/home/al/Documents/node/admin-next/node_modules/react-dom/cjs/react-dom-server.node.development.js:3988:27) at render (/home/al/Documents/node/admin ...

Having trouble with React throwing a SyntaxError for an unexpected token?

Error message: Syntax error: D:/file/repo/webpage/react_demo/src/App.js: Unexpected token (34:5) 32 | 33 | return ( > 34 <> | ^ 35 <div className="status">{status}</div> 36 <div className=&quo ...

Docker Container Crashing without Any Error Logs in NextJS Application

Currently, I am facing an issue with running a NextJS app in a docker container. To connect to my database, I am utilizing Prisma and implementing NextAuth for OAuth. When running the application on my local machine, the login process works smoothly as ex ...

What is the best way to structure a nested object model in Angular?

Issue occurred when trying to assign the this.model.teamMembersDto.roleDto to teamMembersDto. The error message states that the property roleDto does not exist on type TeamMembersDropdownDto[], even though it is nested under teamMembersDto. If you look at ...

The NextJS development server is frequently losing connection

Issue While working on my NextJS project, I've been experiencing occasional disruptions with my development server. Whenever I update my code, I encounter random occurrences of the dev server disconnecting and displaying the error message below: Type ...

A guide on transferring images from Next JS to Strapi API

Is it possible to upload an image from NextJS to the Strapi Media library successfully? I am facing an issue where after uploading the image from the NextJS frontend, it gets stored in both my Strapi Media library and Cloudinary account, but it doesn' ...

having difficulties adjusting the size of the SVG element

I have been struggling to resize an SVG element that I imported into my React project. No matter what methods I try, I can't seem to get it right. First, I import the SVG file: import SVG from "../icon.svg" Then, I attempt to use it as an ...