I am trying to create Contentful dynamic pages in Gatsby + Typescript. Right now, I am able to fetch data while using GraphQL in a browser. The problem arises when I try to fetch data in gatsby-node.ts
. It seems the pages are being generated but not completely. Also, I get this error:
ERROR #12100 API.TYPESCRIPT.TYPEGEN
There was an error while trying to generate TS types from your GraphQL queries:
Error: GraphQL Document Validation failed with 1 errors; Error 0: This anonymous operation must be the only defined operation. at /home/ugnius/GIT/New-webpage/gatsby-node.ts:1:1
See our docs page for more info on this error: https://gatsby.dev/graphql-typegen
failed Generating GraphQL and TypeScript types - 0.109s
gatsby-node.ts
import type { GatsbyNode } from 'gatsby';
import * as path from 'path';
export const createPages: GatsbyNode['createPages'] = async ({ graphql, actions }) => {
const { createPage } = actions;
const request = await graphql<Queries.Query>(`
{
allContentfulInsight {
edges {
node {
title
slug
}
}
}
}
`);
const insightTemplate = path.resolve('./src/templates/Insight.tsx');
const insights = request?.data?.allContentfulInsight.edges;
insights?.forEach((insight, index) => {
createPage({
path: `insights/${insight.node.slug}`,
component: insightTemplate,
context: {
slug: insight.node.slug,
},
});
});
};
src/templates/Insight.tsx
import * as React from 'react';
import { graphql } from 'gatsby';
const InsightTemplate: React.FC<Queries.InsightBySlugQuery> = (data) => {
const title = data?.contentfulInsight?.title; // => undefined
console.log(data); // prints correct data from Contentful but it is undefined in code
return (
<>
<h1>{title}</h1>
</>
);
};
export default InsightTemplate;
export const query = graphql`
query InsightBySlug($slug: String!) {
site {
siteMetadata {
title
}
}
contentfulInsight(slug: { eq: $slug }) {
title
content {
raw
}
}
}
`;
gatsby-types.dts
declare namespace Queries {
// ...
type Query = {
readonly allContentfulInsight: ContentfulInsightConnection;
// ...
};
// ...
type ContentfulInsightConnection = {
readonly edges: ReadonlyArray<ContentfulInsightEdge>;
// ...
};
// ...
type ContentfulInsightEdge = {
readonly node: ContentfulInsight;
// ...
};
// ...
type ContentfulInsight = ContentfulEntry & ContentfulReference & Node & {
readonly slug: Maybe<Scalars['String']>;
readonly title: Maybe<Scalars['String']>;
readonly content: Maybe<ContentfulInsightContent>;
// ...
};
// ...
type InsightBySlugQueryVariables = Exact<{
slug: Scalars['String'];
}>;
type InsightBySlugQuery = {
readonly site: { readonly siteMetadata: { readonly title: string | null } | null } | null;
readonly contentfulInsight: {
readonly title: string | null;
readonly content: { readonly raw: string | null } | null;
} | null;
};
}
What is wrong with my configuration?
To fix ERROR #12100 API.TYPESCRIPT.TYPEGEN
, you need to change GraphQL query in gatsby-node.ts
from
const request = await graphql<Queries.Query>(`
query AllInsights {
allContentfulInsight {
edges {
node {
title
slug
}
}
}
}
`);
to
const request = await graphql<Queries.Query>(`
{
allContentfulInsight {
edges {
node {
title
slug
}
}
}
}
`);
To fix Insight.tsx
you need properly describe template props:
import * as React from 'react';
import { graphql } from 'gatsby';
interface InsightTemplateProps {
data: {
site: {
siteMetadata: { title: string };
};
contentfulInsight: {
title: string;
content: { raw: string };
};
};
}
const InsightTemplate: React.FC<InsightTemplateProps> = ({ data }) => {
const title = data.contentfulInsight.title;
return (
<>
<h1>{title}</h1>
</>
);
};
export default InsightTemplate;
export const query = graphql`
query InsightBySlug($slug: String!) {
site {
siteMetadata {
title
}
}
contentfulInsight(slug: { eq: $slug }) {
title
content {
raw
}
}
}
`;