Responsive hamburger icon using React Hooks

Cover Image for Responsive hamburger icon using React Hooks
Ali Bentaleb
Ali Bentaleb

On the CSS HTML category, we have learned about how you can build responsive hamburger icon using css import combined with media queries. In this article, we are going to do the same mechanism in a beautiful manner using React and React hooks. First things first, let's build our Header Component.

React header Component

So our header component at first will be a simple function which returns our head component, we are using Next Link component and we have named the Header.module.css by headerStyles, so this way we can have multiple imports of css files in the same js file with different names, which makes debugging more easier. Let's take a look at our js code then

import headerStyles from "../styles/Header.module.css";
import React from "react";
import Link from "next/link";

const Header = () => {
  return (
    <div className={headerStyles.headerContainer}>
      <Link href="#">
        <a className="fa fa-bars"></a>
      </Link>
      <>
        <Link href="/">Home</Link>
        <Link href="/about">About</Link>

      </>
    </div>
  );
};
export default Header;

The JS code shown above is using arrow functions introduced in ES6, you can take a glimpse in to learn more. The css code for headerContainer would be

@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css");

.headerContainer {
  max-width: 100%;
  height: 50px;
  border-top: 1px solid #eaeaea;
  display: flex;

  justify-content: left;
  align-items: center;
  background-color: black;
  margin-bottom: 1rem;
}

So this will display a header menu with hamburger icon, Home and about links as the below picture is showing: Plain bar Menu with React,Next Link and hamburger icon

Display/hide the hamburger icon with the useState hook

Pretty simple ha, so let's take it a step further and introduce some React hooks to make the hamburger icon display only when the screen view is less than 600 pixels for example, which is ideal for mobile screens.

Now, we will try to hide the menu when the hamburger icon is clicked, and showed it again when it is clicked twice, to do this, we shall get the help of React hook useState to invoke a new rendering when state is changed. The code will look like :

import headerStyles from "../styles/Header.module.css";

import React, { useState } from "react";
import Link from "next/link";

const Header = () => {
  //A const called className and its method to change the className,
  //it is first initialized to the headerContainer style.
  const [className, setclassName] = useState(headerStyles.headerContainer);

  // Define the method onClick to trigger state const className whenever

  // we click on the hamburger icon and then ask React to give us a new
  // rendering for the header component since state has been changed.
  // The method compare the className to headerContainer and does the opposite
  // if they are equal.
  const onClick = () =>
    className === headerStyles.headerContainer
      ? setclassName(headerStyles.headerContainerA)
      : setclassName(headerStyles.headerContainer);


  return (
    <div className={headerStyles.headerContainer}>
      <Link href="#">
        <a className="fa fa-bars" onClick={onClick}></a>
      </Link>
      {/* We apply the className to our div className, and on each click 
      on the hamburger icon, the menu is either hidden or displayed */}
      <div className={className}>
        <Link href="#">Home</Link>
        <Link href="/about">About</Link>
      </div>
    </div>
  );
};
export default Header;
So basically, we have defined a new state constant called className, and defined the method onClick to call whenever we clicked on the hamburger icon, this method is simply comparing the class style contained in the className, if the className is equal to headerContainer , then the next click will set the className to headerContainerA, React will notice then that the component state has been changed and will render again the header component with the new style applied. We have defined also a new css class called headerContainerA to apply, which set the display to none whenever we click on the hamburger icon.
.headerContainerA {
  max-width: 100%;
  height: 50px;
  border-top: 1px solid #eaeaea;
  display: none;
  justify-content: left;
  align-items: left;
  background-color: black;
  margin-bottom: 1rem;
  color: white;
}

Responsive hamburger icon with the useEffect hook

As you might notice, the hamburger icon is always appearing whether the screen has a big width or small width, so in order to have the responsive effect and choose what to display based on width, we are going to use the effect hook.

import headerStyles from "../styles/Header.module.css";
import Link from "next/link";
import React, { useState, useEffect } from "react";

const Header = () => {
  //A const called className and its method to change the className,
  //it is first initialized to the headerContainer style.
  const [className, setclassName] = useState(headerStyles.headerContainer);
  //choose to show or not show the hamburger icon
  const [show, setShow] = useState(false);

  useEffect(() => {
    //browser listener on media with criteria max-width
    //if matched , the const show=true otherwise it is set to false
    const media = window.matchMedia("(max-width: 600px)");
    media.addEventListener("change", () => {
      media.matches ? setShow(true) : setShow(false);
    });
  }, []);

  // Define the method onClick to trigger state const className whenever
  // we click on the hamburger icon and then ask React to give us a new
  // rendering for the header component since state has been changed.
  // The method compare the className to headerContainer and does the opposite
  // if they are equal.
  const onClick = () =>
    className === headerStyles.headerContainer
      ? setclassName(headerStyles.headerContainerA)
      : setclassName(headerStyles.headerContainer);

  return (
    <div className={headerStyles.headerContainer}>
      {/* based on show value in the useEffect, we choose to show or hide the icon*/}
      {show ? (
        <Link href="#">
          <a className="fa fa-bars" onClick={onClick}></a>
        </Link>
      ) : (
        <div></div>
      )}
      {/* We apply the className to our div className, and on each click 
      on the hamburger icon, the menu is either hidden or displayed */}
      (<div className={className}>
        <Link href="/">Home</Link>
        <Link href="/about">About</Link>
      </div>)
    </div>
  );
};
export default Header;

So when the screen view is less than 600 pixels, we got this view : responsive bar Menu with React,React hooks useState, useEffect nNext Link and hamburger icon and when the screen is wider, the icon is simply dissapearing, you can try and copy the code, shrink the browser view and see by yourself. That's it folks.