Next.js Discord

Discord Forum

Parent layout with common sidebar links, and child layout inserting additional links

Answered
Arboreal ant posted this in #help-forum
Open in Discord
Arboreal antOP
Hi All,

I'm working on an app router nextjs app which has a top navbar and sidebar. I've got everything working great on the desktop view, but am struggling to get it working well on mobile.

Ideally I'd like the parent layout to include a hamburger icon which opens a sidebar with the top nav links.

Below these nav links I'd also like to add links from the child layout.

I.e. if I have the following structure:
(platform)
  settings
    - layout.tsx
  - layout.tsx


The platform links might be:
Nav:
 - dashboard
 - settings 


and when on the settings route
Nav:
 - dashboard
 - settings

Settings:
 - account
 - payment


I'm wondering whether this is feasible or possible to do? I've been trying to play with portals so that a child layout can output to a portal container inside the top layout sidebar, but not had much luck so far. Does anyone have any tips for how to implement this in a clean way?

Alternatively, would it instead be easier/better/cleaner to not have the top navbar and sidebar defined in the top level layout, and instead be a bit wet and have each child layout define the topnav bar and sidebar with their own contents?
Answered by Clown
Technically you can just set the layout as a client and use hooks to check the state and update as you need.

You can also decide to make a navbar component and make it so each page defines its own navbar.
View full answer

20 Replies

Technically you can just set the layout as a client and use hooks to check the state and update as you need.

You can also decide to make a navbar component and make it so each page defines its own navbar.
Answer
Setting the layout to client shouldn't make all the pages it wraps into client component too, since those pages are being passed as props.
However iirc using dynamic function inside layout might make all the pages it surrounds into a dynamic page too (im not sure about this part, you can test it out tho)
If its different for each page you are better off making each page have its own navbar honestly
Arboreal antOP
Yeah that's my backup option. Just have each child layout also redefine the top navbar and sidebar with the relevant content.

I was sort of hoping there would be a way to inject content into the parent layout sidebar somehow.

The topnav, and nav links in the sidebar will be the same on every page, it's just the sidebar could also have some additional content. Which is why duplicating it everywhere feels a bit icky.

I'll play a little more with portals, I feel like that might do the trick if I can get it working, otherwise I'll revert to duplicating the layout in each child.
Also you can technically just switch to a client layout and use some dynamic functions like usePathname instead.
I do that in one of my applications however i dont know how recommended that is, so take it with a pinch of salt
Arboreal antOP
Ok fair enough. I guess where I'm going wrong is I was thinking the topnav and most of the sidebar would be the same for every component, so they'd be ideal to be a layout. But with the {children} being to the right of the sidebar it's not possible to modify it. What I'm asking for isn't really part of the react rendering model via components and props.

I'll make some sort of layout wrapper component thing which takes in children and any additional sidebar content and renders the whole layout. Will that mean that my auth avatar menu thing rerenders on each navigation? I wouldn't want the skeleton loader showing up on every navigation.

Shame I couldn't get the portal idea working. I think that would have been quite cool.

Thanks for your help!
No it shouldnt be re-rendering each time
Arboreal antOP
Ok awesome thanks. I've only recently moved to next from react so I was worried that as it's inside a new component the whole thing would get rerendered.
@Arboreal ant Ok awesome thanks. I've only recently moved to next from react so I was worried that as it's inside a new component the whole thing would get rerendered.
Yeah, layout is that one thing that basically doesnt re-render between navigation and stays still, but you can still have it interactive and it will only re-render parts that are being changed, instead of the entire layout.

Its meant for navigation and stuff anyways. Unlike how it works in normal WebApps where the entire page reloads and renders, in nextjs, the layout stays still and everything inside children prop changes instead
Arboreal antOP
Even if a different layout.ts creates the components?
Does it detect they are the same elements somehow?
What do you mean by that?
Layouts below can't communicate with parent layouts iirc.

However you dont have to make children layouts do that anyways. Just store your routes in a central place then use functions like usePathname to check the path and update them as necessary.

Thats how i do it and i personally dont know other ways but maybe some people here would.
Arboreal antOP
I was just thinking if both /settings/layout.tsx and /organisations/layout.tsx rendered a component, that would be a different instance of that component right? Lets pretend there was a component with a useEffect(()=>{console.log('I'm component X'), []} which was in both layouts we'd see a new console log each time the user navigates between /settings and /organisations right?
Arboreal antOP
Cool I thought so. Was just checking so my mental model is correct. "only re-render parts that are being changed" was throwing me as now I'm putting the navbar and sidebar in all components.
I've made a nice little "PlatformLayout" component that takes in the additional sidebar component and it seems to be working well. I'll need to clean up a bit but I think that should be good 🙂 Thanks for your help!