Reputation: 339
I'm using Strapi to call dynamic data into my website via an API GET request, and I want to generate paths for my dynamic pages. One level of dynamic pages works fine, but the second is a challenge.
My structure is as follows:
[category].js
[category]/[client].js
Both are dynamic, so I have, for example, a category "fashion" with multiple clients. The same goes for other categories like "products".
The first dynamic page works fine in building paths
[dynamic.js]
.
import CategoryCard from "../../../components/portfolio/categoryCard";
import { fetcher } from "../../../lib/api";
export const getStaticPaths = async () => {
const categoryPathResponse = await fetcher(
`${process.env.NEXT_PUBLIC_STRAPI_URL}/categories`
);
const data = categoryPathResponse.data;
const paths = data.map((path) => {
return {
params: { category: path.attributes.path.toString().toLowerCase() },
};
});
return {
paths,
fallback: false,
};
};
export async function getStaticProps(context) {
const category = context.params.category;
const categoryPropsResponse = await fetcher(
`${process.env.NEXT_PUBLIC_STRAPI_URL}/categories?filters[path][$eq]=${category}&?populate[0]=clients&populate[1]=clients.thumbnail`
);
return {
props: { category: categoryPropsResponse },
};
}
const CategoryOverviewPage = ({ category }) => {
const data = category.data;
const categoryTitle = data[0].attributes.Category;
return (
<>
{console.log('data for category before card', data)}
<div className="flex px-4 mt-24 lg:mt-12 lg:px-20">
<div>
<h1 className="[writing-mode:vertical-lr] [-webkit-writing-mode: vertical-lr] [-ms-writing-mode: vertical-lr] rotate-180 text-center">
{categoryTitle}
</h1>
</div>
<div className="grid grid-cols-[repeat(auto-fit,_minmax(150px,_250px))] gap-4 lg:gap-8 ml-4 lg:ml-32 max-w-[82vw]">
<CategoryCard data={data} />
</div>
</div>
</>
);
};
export default CategoryOverviewPage;
But the complexity comes with the second part, in which I have to create multiple paths per category. I tried and ended up with the following
[clients].js
export const getStaticPaths = async () => {
const categoryPathResponse = await fetcher(
`${process.env.NEXT_PUBLIC_STRAPI_URL}/categories?populate=*`
);
const data = categoryPathResponse.data;
const paths = data.map((path) => {
const category = path.attributes.path.toString().toLowerCase()
const client = path.attributes.clients.map((client) => client.name).toString().toLowerCase().replace(/\s+/g, "-")
return {
params: {
category: category, client: client
},
};
});
return {
paths,
fallback: false,
};
};
export async function getStaticProps(context) {
const category = context.params.category;
const client = context.params.client;
const data = await fetcher(
`${process.env.NEXT_PUBLIC_STRAPI_URL_BASE}/categories?filters[path][$eq]=${category}&?populate[clients][populate]=*&populate[clients][filters][name][$eq]=${client}`
);
return {
props: { client: data },
};
}
It seems to work for categories with only 1 item, which makes sense because a URL (path) is created like index/category/client
.
But when there are multiple clients, it tries to create a path with 1 category and multiple clients attached to the same path, something like this category/client1client2
.
This has to be separated, and for each client, there has to be a new path created like category1/client1
, category1/client2
, category2/client1
, category2/client2
, etc.
Any ideas?
Upvotes: 1
Views: 841
Reputation: 50338
In addition to mapping over the categories data
, you also need to map over the clients array and generate a path entry for each.
Modify the code inside getStaticPaths
in /[category]/[client].js
as follows.
export const getStaticPaths = async () => {
// Existing code...
const paths = data.map((path) => {
const category = path.attributes.path.toString().toLowerCase()
return path.attributes.clients
.map((client) => {
const clientDetails = client.name.toLowerCase().replace(/\s+/g, "-")
return {
params: {
category: category, client: clientDetails
}
};
})
}).flat() // Flatten array to avoid nested arrays;
return {
paths,
fallback: false,
};
};
Upvotes: 1