Reputation: 860
I would like to create dynamic pages when I click a tag in an article or elsewhere on my website.
I'm using Next.js, SSG, and fetching the articles containing the tags from Contentful with the following GraphQL queries:
export async function getArticles() {
const articlesQuery = gql`
{
articleCollection(order: date_DESC) {
items {
title
slug
excerpt
date
contentfulMetadata {
tags {
name
id
}
}
featuredImage {
title
url
width
height
}
author {
name
photo {
fileName
url
width
height
}
title
twitterProfile
linkedInProfile
slug
}
}
}
}
`;
return graphQLClient.request(articlesQuery);
}
export async function getArticle(slug) {
const articleQuery = gql`
query getArticle($slug: String!) {
articleCollection(limit: 1, where: { slug: $slug }) {
items {
title
slug
excerpt
date
contentfulMetadata {
tags {
name
id
}
}
featuredImage {
title
url
width
height
}
author {
name
photo {
fileName
url
width
height
}
title
twitterProfile
linkedInProfile
slug
}
content {
json
links {
entries {
block {
sys {
id
}
__typename
... on VideoEmbed {
title
embedUrl
}
... on CodeBlock {
description
language
code
}
}
}
assets {
block {
sys {
id
}
url
title
width
height
}
}
}
}
}
}
}
`;
return graphQLClient.request(articleQuery, {
slug,
});
}
The contentfulMetadata is where the tags come from:
contentfulMetadata {
tags {
name
id
}
}
This is my [id].jsx file:
import { getArticles, getArticle } from "@utils/contentful";
export async function getStaticPaths() {
const data = await getArticles();
return {
paths: data.articleCollection.items.map((article) => ({
params: { id: article.contentfulMetadata.tags[0].id },
})),
fallback: false,
};
}
export async function getStaticProps(context) {
const data = await getArticle(context.params.id);
return {
props: { article: data.articleCollection.items[0] },
};
}
export default function TagPage({ article }) {
return (
<div>
<h1>{article.contentfulMetadata.tags.id}</h1>
</div>
);
}
I get the following error:
Error: Error serializing `.article` returned from `getStaticProps` in "/tags/[id]". Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.
When console.log(data.articleCollection.items.contentfulMetadata.tags.id);
or console.log(data.articleCollection.items.contentfulMetadata.tags[0].id);
within getStaticPaths function it provides the following error:
TypeError: Cannot read property 'tags' of undefined
Can anyone show how to create a dynamic page ([id].jsx) file, which shows the tag id as the header <h1>
as well as all articles containing the same tag?
Upvotes: 0
Views: 683
Reputation: 345
Contentful DevRel here 👋🏼.
article.contentfulMetadata.tags
is an array, as an entry can have more than one tag. So you'll need to access the tag you want via article.contentfulMetadata.tags[0].id
or article.contentfulMetadata.tags[desired_index].id
and so on.
Here's an example GraphQL query:
query {
blogPostCollection {
items {
contentfulMetadata {
tags {
id
name
}
}
}
}
}
And here's the response with tags as an array:
"data": {
"blogPostCollection": {
"items": [
{
"contentfulMetadata": {
"tags": [
{
"id": "salmastag",
"name": "Salma s tag"
}
]
}
},
{
"contentfulMetadata": {
"tags": []
}
}
]
}
}
}
Notice how if a blog post doesn't have any PUBLIC tags assigned (the second entry in the response), an empty array is returned — you might want to do some safety checking in your code for this.
Upvotes: 2