Home > other >  hamburger toogle button not working react
hamburger toogle button not working react

Time:03-15

import React, { useState, useEffect, useRef } from "react";
import { Link } from "react-router-dom";
import "./index.css";


const Navbar = () => {

    const [isMenuOpen, setIsMenuOpen] = useState(false);
    const toggle = () => setIsMenuOpen(!isMenuOpen);
    const ref = useRef()
    useEffect(() => {
        const checkIfClickedOutside = e => {
          if (isMenuOpen && ref.current && !ref.current.contains(e.target)) {
            setIsMenuOpen(false)
          }
        }
        document.addEventListener("mousedown", checkIfClickedOutside)
        return () => {
          document.removeEventListener("mousedown", checkIfClickedOutside)
        }
      }, [isMenuOpen])

    return (
        <>
            <header>

                <nav>
                    <div className="nav">

                        <div className="nav-brand">
                            <Link to="./" className="text-black">Website</Link>
                        </div>
                        <div className="toggle-icon" onClick={toggle}>
                            <i id="toggle-button" className={isMenuOpen ? 'fas fa-times' : 'fas fa-bars'} />
                        </div>
                        {isMenuOpen && (
                            <div className={isMenuOpen ? "nav-menu visible" : "nav-menu"} ref={ref}>
                                <ul className="main-menu">

                                    <li><Link to="./" onClick={toggle}>Home</Link></li>
                                    <li><Link to="./blog" onClick={toggle}>Blog</Link></li>
                                    <li className="drp">
                                        <p className="dropbtn">Find <i className="fa-solid fa-angle-down"></i></p>
                                        <ul className="dropdown-content">
                                            <li><Link to="./find/portable-keyboards" onClick={toggle}>Portable Keyboards</Link></li>
                                        </ul>
                                    </li>
                                    <li className="drp">
                                        <p className="dropbtn">More <i className="fa-solid fa-angle-down"></i></p>
                                        <ul className="dropdown-content">
                                            <li><Link to="./piano-notes" onClick={toggle}>Piano Notes</Link></li>
                                            <li><Link to="./chords" onClick={toggle}>Chords</Link></li>
                                            <li><Link to="./tools/metronome" onClick={toggle}>Metronome</Link></li>
                                        </ul>
                                    </li>
                                </ul>
                            </div>
                        )}
                    </div>
                </nav>  
            </header>

        </>
    )
}

export default Navbar;

Everything is working fine except the toggle button. The menu is not closing after opening it. The onClick={toggle} function is not working on the close icon. The menu will hide when someone clicks outside the menu component which is working fine. I tried a lot but didn't find any method to resolve it. Can someone try to solve this issue?

CodePudding user response:

Issue

The menu toggle button is outside the element you are attaching the outside click listener to, so when you are trying to close the menu the toggle callback and the checkIfClickedOutside handlers are cycling the isMenuOpen state.

Solution

Wrap both the menu button and the menu in a div for the ref to be attached to. There is also no reason really to check if isMenuOpen is true in the checkIfClickedOutside handler. If isMenuOpen is already false, enqueueing another state update to set it false is generally ignored by React. This allows you to remove it as a dependency.

Example:

const Navbar = () => {
  const [isMenuOpen, setIsMenuOpen] = useState(false);
  const toggle = () => setIsMenuOpen(!isMenuOpen);
  const ref = useRef();

  useEffect(() => {
    const checkIfClickedOutside = (e) => {
      if (!ref.current?.contains(e.target)) {
        setIsMenuOpen(false);
      }
    };
    document.addEventListener("mousedown", checkIfClickedOutside);
    return () => {
      document.removeEventListener("mousedown", checkIfClickedOutside);
    };

  }, []);

  return (
    <>
      <header>
        <nav>
          <div className="nav">
            <div className="nav-brand">
              <Link to="./" className="text-black">
                Website
              </Link>
            </div>
            <div ref={ref}> // <-- ref to this containing div
              <div className="toggle-icon" onClick={toggle}>
                <i
                  id="toggle-button"
                  className={isMenuOpen ? "fas fa-times" : "fas fa-bars"}
                />
              </div>
              {isMenuOpen && (
                <div className={isMenuOpen ? "nav-menu visible" : "nav-menu"}>
                  ....
                </div>
              )}
            </div>
          </div>
        </nav>
      </header>
    </>
  );
};

Edit hamburger-toogle-button-not-working-react

  • Related