Home > front end >  Hamburger menu not working when I change class name using UseState in React
Hamburger menu not working when I change class name using UseState in React

Time:03-10

I am creating a navigation bar for a website, and everything is working fine, and the hamburger menu when you change screen size. However, I also made my navbar fixed as the user scrolls.

The hamburger menu works fine when you are scrolled to the top, but once you start scrolling, the hamburger doesn't click.

If I change the initial state of 'false' to 'true,' it will work in reverse order .. so it will not work when at the top, but it will work when scrolling.

I have been trying to figure this out all day, and I have been attempting to find a solution, but I could not. If anyone could help me, It would be greatly appreciated.

Navbar code:

function Navbar2() {
  const [scrolled, setScrolled] = useState(false);

  const canvasRef = useRef();
  const navLinksRef = useRef();
  const liRefAbout = useRef();
  const liRefServices = useRef();
  const liRefGallery = useRef();
  const liRefTestimonials = useRef();
  const liRefContact = useRef();

  // toggle mobile menu on icon click
  useEffect(() => {
    const burger = canvasRef.current;
    const nav = navLinksRef.current;
    const aboutLink = liRefAbout.current;
    const servicesLink = liRefServices.current;
    const galleryLink = liRefGallery.current;
    const testimonialsLink = liRefTestimonials.current;
    const contactLink = liRefContact.current;

    burger.addEventListener('click', () => {
      nav.classList.toggle('nav-active');
      aboutLink.classList.toggle('list-about-active');
      servicesLink.classList.toggle('list-services-active');
      galleryLink.classList.toggle('list-gallery-active');
      testimonialsLink.classList.toggle('list-testimonials-active');
      contactLink.classList.toggle('list-contact-active');
      burger.classList.toggle('toggle');
    });
  }, [scrolled]);

  // make navbar fixed on scroll
  const handleScroll = () => {
    const offset = window.scrollY;
    if (offset > 80) {
      setScrolled(true);
    } else if (offset < 80) {
      setScrolled(false);
    }
  };
  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
  });

  let x = ['navbar'];
  if (scrolled) {
    x.push('scrolled');
  }

  return (
    <nav className={`navbar ${scrolled ? 'scrolled' : ''}`}>
........

Navbar CSS

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  min-height: 8vh;
  background: transparent;
  transition: all 0.4s linear;

  position: sticky;
  position: -webkit-sticky;
  top: 0;
  z-index: 900;
}

.scrolled {
  position: fixed;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.8);
  backdrop-filter: blur(6px);
  width: 100%;
}

CodePudding user response:

A lot of things can be optimized here codewise.

 useEffect(() => {
    const burger = canvasRef.current;
    const nav = navLinksRef.current;
    const aboutLink = liRefAbout.current;
    const servicesLink = liRefServices.current;
    const galleryLink = liRefGallery.current;
    const testimonialsLink = liRefTestimonials.current;
    const contactLink = liRefContact.current;

    burger.addEventListener('click', () => {
      nav.classList.toggle('nav-active');
      aboutLink.classList.toggle('list-about-active');
      servicesLink.classList.toggle('list-services-active');
      galleryLink.classList.toggle('list-gallery-active');
      testimonialsLink.classList.toggle('list-testimonials-active');
      contactLink.classList.toggle('list-contact-active');
      burger.classList.toggle('toggle');
    });
  }, [scrolled]);

You don't have to add an event listener every time "scrolled" has changed. It's just a function that doesn't care what is "scrolled" state but if the button has been clicked so adding event listener once is good. Second, you don't need to redeclare refs as constants as they will point to the same thing.

Second argument as empty array will trigger the useEffecthook once,

useEffect(() => {
    const burger = canvasRef.current;
    const nav = navLinksRef.current;
    const aboutLink = liRefAbout.current;
    const servicesLink = liRefServices.current;
    const galleryLink = liRefGallery.current;
    const testimonialsLink = liRefTestimonials.current;
    const contactLink = liRefContact.current;

    burger.addEventListener('click', () => {
      nav.classList.toggle('nav-active');
      aboutLink.classList.toggle('list-about-active');
      servicesLink.classList.toggle('list-services-active');
      galleryLink.classList.toggle('list-gallery-active');
      testimonialsLink.classList.toggle('list-testimonials-active');
      contactLink.classList.toggle('list-contact-active');
      burger.classList.toggle('toggle');
    });
  }, []);
  • Related