Home > Back-end >  React responsive nav component es6 function not firing
React responsive nav component es6 function not firing

Time:12-09

I'm not quite sure why the click event is not working. I simply trying the use a responsive accessible navigation but looks like I'm missing something in the constructor or I'm not firing the function properly? I have the feeling that my es6 constructor is not right. Please let me know if you could help me

import React, { Component} from "react";
import {hot} from "react-hot-loader";
import { Link } from "react-router-dom";

import "../styles/navbar.scss"
import cart from '../assets/images/cart.png'


class NavBar extends Component{

  constructor(props){
    super(props);
    this.responsiveNav = this.responsiveNav.bind(this);
  
  }
responsiveNav(){
  const primaryNav = document.querySelector(".nav-items");
  const navToggle = document.querySelector(".mobile-nav-toggle");
  
  navToggle.addEventListener("click", () => {
    console.log('click')
    const visibility = primaryNav.getAttribute("data-visible");
  
    if (visibility === "false") {
      primaryNav.setAttribute("data-visible", true);
      navToggle.setAttribute("aria-expanded", true);
    } else if (visibility === "true") {
      primaryNav.setAttribute("data-visible", false);
      navToggle.setAttribute("aria-expanded", false);
    }
  });
  
  }

 

  render(){
    return(
      <div id={this.props.id} className="navbar">
        

        <button  className="mobile-nav-toggle" aria-controls="nav-items" aria-expanded="false">
        <span className="sr-only">Menu</span>
        </button>
        <nav className="nav">
          <div className="nav-menu flex-row">
            <div className="nav-brand">
                <h2><Link to="/">APP</Link></h2>
            </div>

            <ul className="menu" data-visible="false" className="primary-nav flex">
                <li>
                  <Link to="/">Products</Link>
                </li>
                <li>
                  <Link to="/">News</Link>
                </li>
                <li>
                  <Link to="/">Content</Link>
                </li>
                <li>
                  <Link to="/cart"><img src={cart} alt="cart icon"/><div id="yourcart">Your Cart</div></Link>
                </li>
              </ul>
          </div>
        </nav>
      </div>
    );
  }
} 

export default hot(module)(NavBar);

CodePudding user response:

You have a few things going on here. First, use state to manage visible. Your use of the data attribute makes it look like you're coming from a jQuery like background, and things are done a little differently in React. Second, modern React development uses function components over classes. Classes are still supported, for backwards compatibility, but will eventually go away.

I don't know about your stylesheet, but I'm guessing it's triggering off your aria-expanded attribute to determine if the menu is truly shown via CSS. That being the case, your NavBar becomes something like this.

import React, { useState } from "react";
import { Link } from "react-router-dom";

import "../styles/navbar.scss";
import cart from "../assets/images/cart.png";

export default function NavBar() {
  const [visible, setVisible] = useState(false);

  const onClick = () => setVisible((prev) => !prev);

  return (
    <div id={this.props.id} className="navbar">
      <button
        id="menucontrol"
        className="mobile-nav-toggle"
        aria-haspopup="menu"
        aria-controls="nav-items"
        aria-expanded={visible}
        onClick={onClick}
      >
        <span className="sr-only">Menu</span>
      </button>
      <nav className="nav">
        <div className="nav-menu flex-row">
          <div className="nav-brand">
            <h2>
              <Link to="/">APP</Link>
            </h2>
          </div>

          <ul
            className="menu primary-nav flex"
            id="nav-items"
            aria-expanded={visible}
            aria-labelledby="menucontrol"
          >
            <li>
              <Link to="/">Products</Link>
            </li>
            <li>
              <Link to="/">News</Link>
            </li>
            <li>
              <Link to="/">Content</Link>
            </li>
            <li>
              <Link to="/cart">
                <img src={cart} alt="cart icon" />
                <div id="yourcart">Your Cart</div>
              </Link>
            </li>
          </ul>
        </div>
      </nav>
    </div>
  );
}

You can see here that I've defaulted it's visibility to false, and toggle it's state on button click (I'm guessing your routing change will remove the menu all together, or you'd have to toggle on route change as well). I've also expanded your aria code to mirror the W3C example of this type of component.

This isn't using your hot module reloader only because I'm unfamiliar with it's usage in production.

  • Related