I am new at React, and after going through tutorial hell this is my very first project:
I have a nav component that is responsive, and displays a menu

When the screen goes under 1024px, the menu disappears, and shows a hamburger icon
When I click on the Hamburger Icon it opens a modal (ugly I know, I just did a quick formatting to test the code), I added a blur background because that seems to be the "Modal Trend")
everything works according to plan, I had to add a useEffect hook, because I had a problem when I opened the burgerMenu without closing it and I resized again over 1024px, and then downsized it to under 1024p, the menu was still there. But that was fixed and now it closes whenever the windowSize goes over to 1024px.
Now I notice that everytime I open the Modal, and close the Modal my Nav component re-renders. Which I know its expected behavior because I am changing one of the state variables. But a part of me believes there must be a better way.
For all of this, I have questions (in order of importance):
- Is it important to optimize this? At first glance I don't think these re-render would be too much of a problem in this particular example. All the videos I've seen so far they do it more or less like I did.
- Whether it is important or not. What is the best way for me to optimize this? What would be the appropriate approach to make a Modal?. Putting the state directly on the Modal would be an option I suppose, but I wonder how could I manage the conditional rendering on my Nav bar is that is the case.
- I also have a question regarding my Nav component, the part of the code when I am setting the dependencies for useEffect, I don't know if I am being redundant by putting those two dependencies. Part of me thinks that !isMobile is the only important part to have as a dependency. But I didnt want the effect to be run every time it changes from Mobile to non-Mobile, if the modal is Closed, so I put the condition to only do it if the isModalOpen, and that made me think I should include it in the dependency array as well, but not 100% sure about it.
I turned Strict Mode Off while testing the console, just to ensure there aren't artificial double re-renders by react.
This is the code of my Nav component
import { dhLogo } from "../assets";
import { navSections } from "../constants";
import { GiHamburgerMenu } from "react-icons/gi";
import { useEffect, useState } from "react";
import Modal from "../components/Modal";
import useWindowSize from "../hooks/useWindowSize";
const Nav = () => {
console.log(`Nav is rendering`);
const [isModalOpen, setModalOpen] = useState(false);
const isMobile = useWindowSize();
useEffect(() => {
if (!isMobile&&isModalOpen) {
setModalOpen(false);
}
console.log("use Effect is being applied");
}, [isMobile, isModalOpen]);
const toggleModal = () => {
setModalOpen(!isModalOpen);
}
return (
<header className=" padding-x py-8 absolute z-10 w-full" >
<nav className=" flex justify-between items-center max-container " >
<a href="/">
<img src={dhLogo}
width={200}
alt=""
/>
</a>
<ul className="flex flex-grow justify-center align-middle gap-16 max-lg:hidden">
{navSections.map((item, index) => (
<li className="font-palanquin text-slate-gray text-2xl cursor-pointer hover:text-red-500"
key={index}
>{item.link}
</li>
))}
</ul>
<div className="relative lg:hidden">
{isModalOpen ? <Modal toggleModal={toggleModal}/> : <GiHamburgerMenu size={38} onClick={toggleModal}/> }
</div>
</nav>
</header>
)
}
export default Nav
This is the code of my CustomHook useWindowSize
import { useState, useEffect } from "react";
const breakpoint = 1024;
const useWindowSize = () => {
const [isMobile, setIsMobile] = useState(window.innerWidth < breakpoint);
useEffect(() => {
const handleSize = () => {
setIsMobile(window.innerWidth < breakpoint);
}
window.addEventListener("resize", handleSize)
return () => {
window.removeEventListener("resize", handleSize);
}
}, [])
return isMobile;
}
export default useWindowSize
And Finally, this is the code of my ugly Modal
import { navSections } from "../constants";
const Modal = ({toggleModal}) => {
console.log('Modal is Rendering');
return (
<div className="fixed inset-0 bg-black bg-opacity-30 backdrop-blur-md z-40">
<div className="absolute top-0 right-0">
<div className="bg-gray-300 relative border-2 border-purple-800 top-12 right-4 flex flex-col items-center justify-center px-4 py-4 rounded-2xl">
<h1 className="text-wood-orange font-bold text-xl leading-8 underline mb-5">Navigation</h1>
<div className="flex flex-col items-center gap-5"> {navSections.map((item, index) => (
<a className="font-palanquin text-slate-gray text-xl cursor-pointer hover:text-red-500"
key={index}
>{item.link}
</a>))}
<button onClick={toggleModal}>Close</button>
</div>
</div>
</div>
</div>
)
}
export default Modal

