我正在尝试使用 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>
控制台可以工作,但对于类型,它只显示正在加载。
我的代码生成有什么问题吗?
您在查询中提供的类型不正确。 Codegen 为每个查询生成一个输出类型,这就是您应该使用的类型。该类型仅包含查询中指定的字段,其结构与查询的结构完全匹配。所以在你的例子中,类型看起来像这样:
type ColorDataQuery = {
colors: {
data: [{
attributes: {
color_name: string
}
}]
}
};
如您所见,这种类型的结构比
ColorEntityResponseCollection
嵌套得更深。此外,在这种类型结构中,与 ColorEntity.id
不同,没有 ColorEntityResponseCollection
等字段。
您不需要显式指定此类型。
useQuery
根据提供的查询正文自动确定。然而,这种自动化涉及以下步骤:
import { graphql } from '@/src/__generated__';
const COLOR_DATA = graphql(`
query ColorData{
colors{
data{
attributes{
color_name
}
}
}
}
`);
运行codegen命令:
npx graphql-codegen
通过
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>
);
}