Reputation: 151
I am new in NextJS (I am using Next JS 13) and I struggle with the next issue:
In RootLayout I want to add the Header (with a hamburger menu icon), a sidebar menu and the {children} (this is the layout for the entire app)
How can I toggle the display of the sidebar when clicking on the Hamburger icon? Normally I put a state inside the RootLayout and toggle that state from the Header component, and based on it's value show/hide the sidebar component.
But as i read in docs, the RootLayout is a server component and can't have the directive 'use client' (even if it was possible, if I understood correctly, {children} will be also client rendered, so it's not ok)
Upvotes: 3
Views: 3218
Reputation: 91
like @Mer Mer said, make a separate component for your side bar navigation as a client component.
Then use a Global Context that holds the state of the menu. You'll also gain the ability to trigger the menu's state in any other client component
'use client'
import { CartButton } from '@components/ecommerce/CartButton'
import { NavWichButton } from './NavWichButton'
import { SessionBadge } from './Session'
export function Nav() {
const { isNavOpen, toggleNav } = useNavControl()
return (
<nav>
<button
onClick={e => toggleNav()}
id='navwich'
className={getStyles(isNavOpen)}
>
{isNavOpen ? 'Opened' : 'Closed' }
</button>
<ul className={styles.menu_main}>
<li> <a href={`/home`}> Home </a> </li>
<li> <a href={`/shop`}> Shop </a> </li>
<li> <a href={`/blog`}> Blog </a> </li>
<li> <a href={`/users`}> Users </a> </li>
</ul>
</nav>
)
}
'use client'
import { createContext, useContext, useState } from "react";
const defaultCtx = {
isNavOpen: false,
setisNavOpen: (isSearchOpen: boolean) => { },
toggleNav: () => { },
}
const GlobalContext = createContext(defaultCtx)
export const GlobalContextProvider = ({ children }: { children: React.ReactNode }) => {
const [isNavOpen, setisNavOpen] = useState<boolean>(false)
function toggleNav() { console.log('toggle nav');
setisNavOpen(!isNavOpen) }
return (
<GlobalContext.Provider value={{
isNavOpen, setisNavOpen, toggleNav,
}}>
{children}
</GlobalContext.Provider>
)
};
export function useNavControl() {
const { isNavOpen, setisNavOpen, toggleNav, } = useContext(GlobalContext)
return { isNavOpen, setisNavOpen, toggleNav, }
}
export const useGlobalContext = () => useContext(GlobalContext);
don't forget to wrap the children in your root layout with this global context
Upvotes: 2
Reputation:
Create a separate client component that renders the navbar (with the use client directive), then import it in the rootlayout.
Server components can import and render client components.
Upvotes: 0