1
votes

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?

1

1 Answers

0
votes

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
}