graphql codegen 类型是否正确

问题描述 投票:0回答:1

我正在尝试使用 Strapi 作为无头 CMS,使用打字稿创建一个简单的下一个应用程序。

我只想使用 Strapi 和 graphql 与 typescript 来在下一个应用程序中显示一些内容。

在 Strapi 中,我只有一个颜色内容类型,有两种颜色:红色和蓝色

我在 Strapi 中设置了 graphql,并且在操场上可以正常工作

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

这个输出

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

在下一个应用程序中,我使用 graphql codegen 来生成类型

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

它输出的与颜色相关的类型是

export type Color = {
  __typename?: 'Color';
  color_name?: Maybe<Scalars['String']['output']>;
  createdAt?: Maybe<Scalars['DateTime']['output']>;
  publishedAt?: Maybe<Scalars['DateTime']['output']>;
  updatedAt?: Maybe<Scalars['DateTime']['output']>;
};

export type ColorEntity = {
  __typename?: 'ColorEntity';
  attributes?: Maybe<Color>;
  id?: Maybe<Scalars['ID']['output']>;
};

export type ColorEntityResponse = {
  __typename?: 'ColorEntityResponse';
  data?: Maybe<ColorEntity>;
};

export type ColorEntityResponseCollection = {
  __typename?: 'ColorEntityResponseCollection';
  data: Array<ColorEntity>;
  meta: ResponseCollectionMeta;
};

export type ColorFiltersInput = {
  and?: InputMaybe<Array<InputMaybe<ColorFiltersInput>>>;
  color_name?: InputMaybe<StringFilterInput>;
  createdAt?: InputMaybe<DateTimeFilterInput>;
  id?: InputMaybe<IdFilterInput>;
  not?: InputMaybe<ColorFiltersInput>;
  or?: InputMaybe<Array<InputMaybe<ColorFiltersInput>>>;
  publishedAt?: InputMaybe<DateTimeFilterInput>;
  updatedAt?: InputMaybe<DateTimeFilterInput>;
};

export type ColorInput = {
  color_name?: InputMaybe<Scalars['String']['input']>;
  publishedAt?: InputMaybe<Scalars['DateTime']['input']>;
};

但是如果我尝试在下一个应用程序中使用它,该类型似乎不适用于查询中的数据。

'use client'
import { COLOR_DATA} from '@/graphql/queries'
import { Color, ColorEntityResponse, ColorEntityResponseCollection } from '@/src/__generated__/graphql'
import { useQuery } from '@apollo/client'

const Home = () => {

  const {data, loading} = useQuery<ColorEntityResponseCollection, ColorEntityResponse>(COLOR_DATA)

  if(loading || !data) return <div>Loading</div>

  console.log(data)

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

export default Home;    

如果我删除类型

<ColorEntityResponseCollection, ColorEntityResponse> 

控制台可以工作,但对于类型,它只显示正在加载。

我的代码生成有什么问题吗?

typescript graphql strapi next
1个回答
0
投票

您在查询中提供的类型不正确。 Codegen 为每个查询生成一个输出类型,这就是您应该使用的类型。该类型仅包含查询中指定的字段,其结构与查询的结构完全匹配。所以在你的例子中,类型看起来像这样:

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

如您所见,这种类型的结构比

ColorEntityResponseCollection
嵌套得更深。此外,在这种类型结构中,与
ColorEntity.id
不同,没有
ColorEntityResponseCollection
等字段。

您不需要显式指定此类型。

useQuery
根据提供的查询正文自动确定。然而,这种自动化涉及以下步骤:

  1. 声明查询主体。 声明可能会根据 codegen 配置而有所不同,但在您的情况下,查询正文应如下所示:
import { graphql } from '@/src/__generated__';

const COLOR_DATA = graphql(`
    query ColorData{
      colors{
        data{
          attributes{
            color_name
          }
        }
      }
    }
`);
  1. 运行codegen命令:

    npx graphql-codegen

  2. 通过

    useQuery
    实现查询调用:

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

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

完成这些步骤后,您将看到 IDE 如何突出显示查询输出的类型。

IDE 很可能还会突出显示您尝试访问的字段具有不同的位置。正确的字段访问如下所示:

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

    return (
        <div>
            <ul>
                {data.colors.data.map((color) =>
                    (<li>{color.attributes.color_name}</li>)
                )}
            </ul>
        </div>
    );
}
© www.soinside.com 2019 - 2024. All rights reserved.