I’m trying to achieve a 3 levels dynamic routes in my next js application. So far I just obtain a 2 levels dynamic routes. All the data are coming from a headless CMS. I’m using graphlQL
So far I managed to obtain a 2 levels: blog/[category]/[post]. However I can’t make this working: blog/[category]/[subcategory]/[post]
This is the code for the category:
import Link from "next/link";
import { getCategories, getPosts } from "../../../utils/datocmsHelper";
export default function CategoriesPage({ category, subcategories, posts }) {
return (
<div>
<h1>{category.categoryName}</h1>
<h2>sub-categories inside Category:</h2>
<ul>
{subcategories.map((subcategory) => (
<li key={subcategory.slug}>
<Link href={`/blog/${category.slug}/${subcategory.slug}`}>
{subcategory.slug}
</Link>
</li>
))}
</ul>
<h2>Posts:</h2>
<ul>
{posts.map((post) => (
<li key={post.slug}>
<Link href={`/blog/${category.slug}/${post.slug}`}>
{post.slug}
</Link>
</li>
))}
</ul>
</div>
);
}
export async function getStaticProps(ctx) {
const categoriesData = await getCategories();
const postsData = await getPosts();
const currentCategory = categoriesData.allCategories.find(
(category) => category.slug === ctx.params.category
);
const subcategoriesInCategory = categoriesData.allCategories.filter(
(subcategory) => subcategory.category.slug === currentCategory.slug
);
const postsInCategory = postsData.allPosts.filter(
(post) => post.category.slug === currentCategory.slug
);
return {
props: {
category: currentCategory,
subcategories: subcategoriesInCategory,
posts: postsInCategory,
},
};
}
export async function getStaticPaths() {
const categoriesData = await getCategories();
return {
paths: categoriesData.allCategories.map((category) => ({
params: {
category: category.slug,
},
})),
fallback: false,
};
}
this is the code for the subcategory:
import { getPosts, getCategories } from "../../../../utils/datocmsHelper";
export default function CategoriesPage({ subcategory }) {
return (
<div className="flex flex-col">
<h1>title: {subcategory.slug}</h1>
<p>Category: {subcategory.category.slug}</p>
<p>subcategory general content</p>
</div>
);
}
export async function getStaticProps(ctx) {
const subcatogoriesData = await getCategories();
const currentsubcategory = subcatogoriesData.allCategories.find(
(subcategory) => subcategory.slug === ctx.params.subcategory
);
return {
props: {
subcategory: currentsubcategory,
},
};
}
export async function getStaticPaths() {
const catogoriesData = await getCategories();
return {
paths: catogoriesData.allCategories.map((category) =>
category.children.map((subcategory, i) => ({
params: {
subcategory: subcategory.slug,
category: category.category.slug,
},
}))),
fallback: false,
};
}
and this for the post:
import { getPosts } from "../../../../../utils/datocmsHelper";
export default function CategoriesPage({ post }) {
return (
<div className="flex flex-col">
<h1>title: {post.title}</h1>
<p>Category: {post.category.slug}</p>
<p>post general content</p>
</div>
);
}
export async function getStaticProps(ctx) {
const postsData = await getPosts();
const currentPost = postsData.allPosts.find(
(post) => post.slug === ctx.params.post
);
return {
props: {
post: currentPost,
},
};
}
export async function getStaticPaths() {
const postsData = await getPosts();
return {
paths: postsData.allPosts.map((post) => ({
params: {
post: post.slug,
category: post.category.slug,
},
})),
fallback: false,
};
}
2
2 Answers
One way is to just use an index file at the end.
blog/[category]/[subcategory]/[post]/index.tsx
// can access category/subcategory/post values e.g. at blog/general/travel/5/
You haven’t provided an error message so I’ll have to do some guessing. For any level of nesting you need to provide values for the preceding dynamic portions of the path as well as for the current page. I think you’re missing a params
value in your Post page i.e. if you have 3 levels of nesting such as: /[category]/[subcategory]/[id]
then in your [id].js
page your getStaticPaths
function would look something like:
export async function getStaticPaths() {
const postsData = await getPosts();
return {
paths: postsData.allPosts.map((post) => ({
params: {
post: post.slug,
subcategory: post.subcategory.slug,
category: post.category.slug,
},
})),
fallback: false,
};
}
Add a photo of your folder structure of pages directory.
Feb 7 at 20:51
At the moment I can't upload a photo but, basically, I've created a folder inside every folder, with the relative index.js file
Feb 7 at 21:27