Responsive hamburger icon using React Hooks


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:
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;
.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 :
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.