Bart
Bart

Reputation: 339

Creating multiple dynamic paths with Strapi, with nested dynamic pages

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:

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

Answers (1)

juliomalves
juliomalves

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

Related Questions