Next.js Discord

Discord Forum

Breadcrumbs component in app router (using the Layout)

Unanswered
Large oak-apple gall posted this in #help-forum
Open in Discord
Large oak-apple gallOP
My understanding is that it is best to use the layout.tsx for all shared ui, and the page.tsx for page-specific items. I am wanting to create a breadcrumbs component, but am a bit hung up on how to accomplish this without rendering a <Breadcrumbs items={breadcrumbs} /> on every page (should be in the layout, correct?). The goal is to have the layout-specific breadcrumb passed through to the layout on render (almost as a child?). I think I am missing something obvious to allow for this.

Preferred method/example:

Dashboard
- page.tsx
- layout.tsx (with breadcrumb data provided as label="Dashboard" href="example.com", would render "Dashboard" with href to example.com)
-- Places
-- page.tsx
-- layout.tsx (with breadcrumb data provided as label="Places" href="example1.com", breadcrumbs would render as "Dashboard" with href to example.com, then "Places" with href to example1.com)
--- [placeId]
--- page.tsx
--- layout.tsx (with breadcrumb data provided as label={place.label} href={place.url}, breadcrumbs would render as "Dashboard" with href to example.com, then "Places" with href to example1.com, then "PlaceId" with href to "PlaceUrl" )

Something along those lines, where the child layout provides the parent layout with another item to render. Currently using typescript with tailwindcss, making use of usePathname to conditionally render the component (I can't include due to the text length restrictions).

Honestly, even the most basic example of how to achieve this would be much appreciated!

16 Replies

European sprat
you can see an example of an implementation from vercel there
code button takes you to the code for it
Large oak-apple gallOP
Hi @European sprat, thanks for the prompt reply. I've been looking at that screen all day, and don't think that it applies for the method I'm going for. Preferably, I want to have a <PageHeader items={items}/> component that renders on the parent layout that maintains the style I want. I don't see how, if additional layouts are rendered just as children, I could accomplish this. I want the items to be inline for the parent pageheader component (rather than having a brand new pageheader render for each child as shown in the playground's <TabGroup /> usage. Thoughts, or am I misunderstanding something?
Basically appending the breadcrumb to the previous layout breadcrumbs
European sprat
i'm not sure exactly what the best way to implement it would be for you. layouts and server/client components and what each can do can be a bit mind bending so might just take more trial and error and looking for other examples
Large oak-apple gallOP
Unfortunately not that many examples floating out there, but thanks for the assistance. I'll leave this post open just in case someone else has done something similar.
Large oak-apple gallOP
European sprat
ahh yeah i see. inside <Breadcrumbs/> you can read the current route and then use that to display/highlight the <Breadcrumb/>
in my "navItems" object i have a show property which checks a few different things whether to show it or not like if the current pathname is equal to the path i expect, etc
Large oak-apple gallOP
Correct - I already utilize usePathname, but that just returns the url which wouldnt allow me to set the label based on the url. Right now I return a list like export default function PlaceLayout({ children }: PlaceLayoutProps, ) {

const breadcrumbs = [
{label: "place", href: "/dashboard/places/place", disabled: true},
]

return (
#Unknown Channel
<div className="flex flex-col">
<PageHeader breadcrumbs={breadcrumbs} />
{children}
</div>
</>
)
}
but that doesn't help to append the item to the parent layout's breadcrumb items.
European sprat
i guess i'm confused why you are talking about appending an item to the parent layout breadcrumb items or why in your image you mention breadcrumbs in other children layouts. why can't you just have the entire breadcrumbs component in the root layout with the label, href and disabled properties?
Large oak-apple gallOP
Say I stuck it into the root layout (and ignoring the page header). If I did, I would need to conditionally render all possible breadcrumbs from the url (which doesn't really work if I am fetching a dynamic route through the layout). I want to push what the breadcrumb is for a layout based on what is entered as a Breadcrumb within each layout segment, which is then added to the list of breadcrumbs in the root. It wouldn't be passed through via the layout's children, not sure how it would work as a prop
European sprat
if you do need to do it that way, you'll probably want to look at a state management library or context
I see, in this case, you can use the Context API provided by React.

<Context.Provider value={[...previousItems, breadcrumbItem]}>
  <Breadcrumb />
  {children}
</Context.Provider>


You can do that in every layout: receive the context and add a new item.
Finally, create a client component that renders all the items received from the context, and put it in the closest layout (where the last item added)
Large oak-apple gallOP
Yeah, good call @European sprat @fuma. I'll give that a whirl- many thanks!