Variable length dynamic route
Unanswered
Japanese pilchard posted this in #help-forum
Japanese pilchardOP
I need help creating some dynamic routes.
## What I want to achieve
The types of routes I want to create are:
- /category/product
- /category/sub-category/product
- /category/sub-category/sub-sub-category/product
You can see that the category nesting of the product can vary. But I still want one page.js file for the categories and one page.js for the product.
## My failed thoughts on solutions
1. /[...categories]/[product] or /[category]/[[...subCategories]]/[product]
This failed because catch-all routes are only available at the very end. But I still have the dynamic product after the catch-all categories. Of course, this is my bad thinking this would work.
2. /[categories]/[product] but with generateStaticParams()
The static params I tried to generate were:
- Top down generating:
Categories page:
return [{ categories: "category/sub-category" }];
Product page:
return [{ product: "product" }]
- Bottom up generating:
Product page:
return [{ categories: "category/sub-category" , product: "product" }]
These didn't work because as soon as you add a "/" it interprets is as moving on to the second dynamic route segment which in this case is the product page.
## Does anyone have a solution to this puzzle?
Thanks for any feedback. ; )
## What I want to achieve
The types of routes I want to create are:
- /category/product
- /category/sub-category/product
- /category/sub-category/sub-sub-category/product
You can see that the category nesting of the product can vary. But I still want one page.js file for the categories and one page.js for the product.
## My failed thoughts on solutions
1. /[...categories]/[product] or /[category]/[[...subCategories]]/[product]
This failed because catch-all routes are only available at the very end. But I still have the dynamic product after the catch-all categories. Of course, this is my bad thinking this would work.
2. /[categories]/[product] but with generateStaticParams()
The static params I tried to generate were:
- Top down generating:
Categories page:
return [{ categories: "category/sub-category" }];
Product page:
return [{ product: "product" }]
- Bottom up generating:
Product page:
return [{ categories: "category/sub-category" , product: "product" }]
These didn't work because as soon as you add a "/" it interprets is as moving on to the second dynamic route segment which in this case is the product page.
## Does anyone have a solution to this puzzle?
Thanks for any feedback. ; )
10 Replies
iirc you give a list
see: https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments
// you did
categories: "category/sub-category"
// but im pretty sure you would do this
categories: ['category', 'sub-category']see: https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments
Japanese pilchardOP
Just gave it a shot and unfortunately that doesn't work. The array values for params are only for catch-all segments and I can't use a catch-all segment for the categories because it's not the end of the path, I still have [product] after the categories. 😢
who does the last one have to be dynamic?
can't you just have the catch all and get the last one or just have
/product/page.tsx if it won't be anything elseJapanese pilchardOP
Hmm.. I'm trying to think how I would accomplish what I'm trying to achieve with a catch-all at the end.
Because the product page itself only has one dynamic segment, one slug. But the category page can have multiple varying segments/slugs that lead to it. And the category is the parent of the product, it must come before the product.
Because the product page itself only has one dynamic segment, one slug. But the category page can have multiple varying segments/slugs that lead to it. And the category is the parent of the product, it must come before the product.
@riský can't you just have the catch all and get the last one or just have `/product/page.tsx` if it won't be anything else
Japanese pilchardOP
I hope I did understand this correctly but do correct me if my message didn't make sense in this context.
im just thinking you can just have one catch all and use the last element of list to know effectivly last dynamic route
Japanese pilchardOP
True, I could use that to identify the correct product to render. But I also need to render the category page when the url has a category slug at the end.
So if I have a file at "[category]/[...product]/page.js" and that page gets the url of "/category-1/sub-category-2/product-1". I can get the product id by "params.product.at(-1)" and render the correct product on the product page. But it will also render the product page when the url is "/category-1/sub-category-2" when it should be rendering the category page, the file at "[category]/page.js".
For this to work I will have to:
1. get the last item in the params array
2. check if it is a product or a category
3. conditionally render <ProductPage /> or <CategoryPage /> respectively.
I would've hoped there would be a better solution with the file based routing rather than relying on conditional rendering based on what's in the url, like the good ol' days with plain React without React Router.
So if I have a file at "[category]/[...product]/page.js" and that page gets the url of "/category-1/sub-category-2/product-1". I can get the product id by "params.product.at(-1)" and render the correct product on the product page. But it will also render the product page when the url is "/category-1/sub-category-2" when it should be rendering the category page, the file at "[category]/page.js".
For this to work I will have to:
1. get the last item in the params array
2. check if it is a product or a category
3. conditionally render <ProductPage /> or <CategoryPage /> respectively.
I would've hoped there would be a better solution with the file based routing rather than relying on conditional rendering based on what's in the url, like the good ol' days with plain React without React Router.
i mean, i would have expected it to work, but ig you have to do this as a fix ðŸ˜
Japanese pilchardOP
Yeah, this does seem like the only work around. 😢 But hopefully somebody else will come around with another solution.
But thank you for your feedback and solution.
But thank you for your feedback and solution.