Using parallel routes to display route related information in layouts
Breadcrumbs can be found in e-commerce, blogs, documentation, and many other types of websites. They are a great way to help users understand where they are in the website hierarchy and navigate back to previous pages. If one should say where they should be placed at code level, it's probably in the layout shared between all the pages that has it. But sometimes it's not that simple. To show information about the current route, you might need information from the url, like the params, which is not available in layouts.
A solution for this might be create the breadcrumbs component as a client component, use a hook to get the params and then display it. But, what happen if the parameter in the url is a slug, and we have to first get the display value for it from a service before showing it on the breadcrumb? Because it's a client component we have to waiy for the server to send the response, for the javascript to download and execute, for the call to the slug service to complete and then finally display that breadcrumb to the user.
Wow, that sounds like a lot of work right? Well, or we can use a parallel route 👇
Pages as components
You can image parallel routes as slots in your page. Your layout receives a prop children
that has the content of the route to display. With parallel routes you can have more of this slots where you decide what to display in each one. And, like pages, they receive the same props, including the params.
Let's do it
You were given a task to update a bakery blog project. You have to show a breadcrumb with the category and its icon and the post title on it.
You can't touch the page
file because it's being handled by a CMS so you can only change the layout or add new files to add the breadcrumb. Let's start by creating a parallel route for our breadcrumb:
|/app |__/[category] |____/[slug] |______/page.js |__/layout.js |__/@breadcrumb |____/[category] |______/[slug] |________/page.js
Now we have a parallel route called breadcrumb
that will match when someone requests the /category/slug
page. Let's add the parallel route to our layout.
export default function RootLayout({ children, breadcrumb }) { return ( <html lang="en"> <body> <header> <Navbar /> {breadcrumb} </header> <main> {children} </main> </body> </html> ) }
In our /@breadcrumb/[category]/[slug]/page.js
let's get category and slug, fetch the display name and display them on screen.
export default async function BreadcrumbPage({ params: { category, slug } }) { const displayName = await fetch(`.../${category}/${slug}`); return ( <nav className="flex gap-4 text-sm opacity-80"> <span className="capitalize">{` > ${category}`}</span> <span> / </span> <span>{displayName}</span> </nav> ); }
Now, Next.js will send the response as soon as it's ready on the server. Also, as this is a page, we can define a loading.js
to display a skeleton while we fetch the display name. You can find a working example in the /demo
route.