0
I have a nextjs app using typescript and a Strapi backend with graphql
I’m trying to simple get the graphql from strapi and display it in the react app.
I’m trying to display a list of font names.
In react I have this query, this works in the playground
import { gql } from "@/node_modules/@apollo/client/core/index";
export const FONT_DATA = gql`
query font_data{
fonts{
data{
attributes{
font_name
}
}
}
}
`
I’m generating types using codegen.
export type Font = {
__typename?: 'Font';
createdAt?: Maybe<Scalars['DateTime']['output']>;
font_name?: Maybe<Scalars['String']['output']>;
publishedAt?: Maybe<Scalars['DateTime']['output']>;
updatedAt?: Maybe<Scalars['DateTime']['output']>;
};
export type FontEntity = {
__typename?: 'FontEntity';
attributes?: Maybe<Font>;
id?: Maybe<Scalars['ID']['output']>;
};
export type FontEntityResponse = {
__typename?: 'FontEntityResponse';
data?: Maybe<FontEntity>;
};
export type FontEntityResponseCollection = {
__typename?: 'FontEntityResponseCollection';
data: Array<FontEntity>;
meta: ResponseCollectionMeta;
};
export type FontFiltersInput = {
and?: InputMaybe<Array<InputMaybe<FontFiltersInput>>>;
createdAt?: InputMaybe<DateTimeFilterInput>;
font_name?: InputMaybe<StringFilterInput>;
id?: InputMaybe<IdFilterInput>;
not?: InputMaybe<FontFiltersInput>;
or?: InputMaybe<Array<InputMaybe<FontFiltersInput>>>;
publishedAt?: InputMaybe<DateTimeFilterInput>;
updatedAt?: InputMaybe<DateTimeFilterInput>;
};
export type FontInput = {
font_name?: InputMaybe<Scalars['String']['input']>;
publishedAt?: InputMaybe<Scalars['DateTime']['input']>;
};
In react I have a simple page where I am calling the query and trying to display the font names
'use client'
import { getDataFromTree } from '@apollo/client/react/ssr'
import withApollo from '../lib/withApollo'
import { FontEntity, FontEntityResponse, FontEntityResponseCollection} from '@/generated'
import { useQuery } from '@apollo/client'
import { FONT_DATA } from '@/graphql/queries'
const Home = () => {
// const data: FontEntityResponse = useThemeContext()?.data;
const {data, loading} = useQuery<FontEntityResponse, FontEntity>(FONT_DATA)
if(loading || !data) return <div>Loading</div>
console.log(Array.isArray(data))
return (
<div>
<ul>
{data?.data?.attributes?.map((font:FontEntity) => (
<li key={font.id}>{font?.font_name}</li>
))}
</ul>
</div>
);
}
export default withApollo(Home, { getDataFromTree });
The map errors with Property 'map' does not exist on type 'Font'
which is because its not an array.
The console.log also says its not an array.
The graphql returns an object but how do I use that with the map, or am I using the wrong type.
Update
if I do console.log(JSON.stringify(data, null, 2))
I get
{
"fonts": {
"__typename": "FontEntityResponseCollection",
"data": [
{
"__typename": "FontEntity",
"attributes": {
"__typename": "Font",
"font_name": "Black"
}
},
{
"__typename": "FontEntity",
"attributes": {
"__typename": "Font",
"font_name": "Jasper"
}
},
{
"__typename": "FontEntity",
"attributes": {
"__typename": "Font",
"font_name": "Varly"
}
},
{
"__typename": "FontEntity",
"attributes": {
"__typename": "Font",
"font_name": "Brother"
}
}
]
}
}
1 Answer
Reset to default
0
I’m not sure how it works with strapi, but usually graphql response looks like this:
data.nameOfYourResolver.arrayObjectOrOtherTypeOfData
Your types are all wrong.
In your case, it should look something like this:
export type FontEntityResponse = {
fonts: Maybe<FontEntityData>; //object
};
export type FontEntityData = {
data: Maybe<FontEntity[]> //Array
};
export type FontEntity = {
attributes: Maybe<Font>; //Object
export type Font = {
fontName: Maybe<string>; //string
data.fonts.data(attribute => {
console.log(attribute.font_name)
//...
})
Again, I don’t know what type of data is it exactly, but your property names are wrongly named
All you need to do is check for the types of these properties
fonts{
data{
attributes{
font_name }}}
You can console.log(JSON.stringify(data, null, 2))
to see all the data inside
Also, I think that in
const {data, loading} = useQuery<FontEntityResponse, FontEntity>(FONT_DATA)
FontEntity should supposed to be used for variable types that are used when fetching this resolver.
3
-
these are the type generated with codegen, I haven't created them
– cdmt2 hours ago
-
I have updated the question with the console log you suggested
– cdmt2 hours ago
-
Well it looks like it generated the wrong types. I updated my answer. Maybe they are outdated or something, but based on the console.log you provided, it is
data.fonts.data.map
– SlothOverlord1 hour ago