I have a Navbar component where I have created a hamburger menu, when I click on the hamburger menu I want to show the menu component, which is a separate component.
I got this working by sharing the data through props.
However, I want the menu to disappear when you click outside the container or when you click on a link.
Clicking outside container works with the npm package react-outside-click-handler but my menu does not close when I click on a link.
This is what I have currently
// navbar
export default function Navbar() {
const [hamburgerOpen, setHamburgerOpen] = useState(false);
const toggleHamburger = () => {
setHamburgerOpen(!hamburgerOpen);
}
return (
<div>
<div className={styles.hamburger + ' cursor-pointer'} onClick={toggleHamburger}>
<span className={styles.hamburgerLine}></span>
<span className={styles.hamburgerLine}></span>
</div>
<OutsideClickHandler
onOutsideClick={() => {
setHamburgerOpen(hamburgerOpen = false);
}}
>
<Menu hamburgerStatus={hamburgerOpen} />
</OutsideClickHandler>
</div>
)
}
// menu
export default function Menu(props) {
return (
<div className={props.hamburgerStatus ? styles.menuContainer : 'hidden'}>
<nav className='bg-secondary text-white w-full max-w-[440px] mt-6 absolute'>
<div className="">
<div className='flex items-center rounded p-3 cursor-pointer transition-all'>
<Link href="/" onClick={props.hamburgerStatus = false}>
Home
</Link>
</div>
<div className='flex items-center rounded p-3 cursor-pointer transition-all'>
<Link href="/contact">
Contact
</Link>
</div>
<div className='flex items-center rounded p-3 cursor-pointer transition-all'>
<Link href="/contact">
Contact
</Link>
</div>
</div>
</nav>
</div>
)
}
Using onClick={props.hamburgerStatus = false} doesn't work, because props is not overwritable.
So what I want is the following:
Hamburger menu needs to opens <Menu /> component when the user clicks on the hamburger menu. Clicking outside the menu component or on a link must close the menu.
How can I get this to work in React?
To close the menu when clicking on a link/navigating to another page, you can add a listener on the next/router's routeChangeStart event, and set the hamburgerOpen state variable to false when it fires. This ensures the menu always closes on client-side navigations.
import { useRouter } from 'next/router';
export default function Navbar() {
const router = useRouter();
const [hamburgerOpen, setHamburgerOpen] = useState(false);
const closeHamburger = () => {
setHamburgerOpen(false);
};
useEffect(() => {
router.events.on('routeChangeStart', closeHamburger);
return () => router.events.off('routeChangeStart', closeHamburger);
}, [router.events]);
// Rest of the component's code
}