I’m trying to rebuild a menu that I had done using a tutorial but in Nextjs instead of react. At the time of doing the tutorial I had used react-router-dom v6 and useLocation. However as I am trying to learn and understand Nextjs more I am unsure if I should be still using react-router-dom (as I understand Next has built in routing) and if not how I should be using useLocation properly or the equivalent of it.I have attached the file and the code below, and really appreciate any input on trying to make this work.
Header.jsx
import React, { useEffect, useState } from "react";
import { FiMenu } from "react-icons/fi";
const Header = () => {
// Need to find Nextjs equivalent
const location = useLocation();
// State for menu button
const [state, setState] = useState({
initial: false,
clicked: null,
menuName: "Menu",
});
// State for disabled button
const [disabled, setDisabled] = useState(false);
// Use effect for page changes
useEffect(() => {
setState({ clicked: false, menuName: "Menu" });
}, [location]);
const handleMenu = () => {
disabledMenu();
if (state.initial === false) {
setState({
initial: null,
clicked: true,
menuName: "Close",
});
} else if (state.clicked === true) {
setState({
clicked: !state.clicked,
menuName: "Menu",
});
} else if (state.clicked === false) {
setState({
clicked: !state.clicked,
menuName: "Close",
});
}
};
// Determine if the menu should be disabled
const disableMenu = () => {
setDisabled(!disabled);
setTimeout(() => {
setDisabled(false);
}, 1200);
};
return (
<div className="w-full mx-auto my-0">
<div className="px-12 py-0">
<div className="relative z-20 flex items-center justify-between h-32">
<div className="text-base">LOGO</div>
<div className="flex flex-row">
<div className="mx-5">
<button>Home</button>
</div>
<div className="mx-5">
<button>Home</button>
</div>
<button
className="ml-10 text-xl font-bold"
disabled={disabled}
onClick={handleMenu}
>
<FiMenu />
</button>
</div>
</div>
</div>
</div>
);
};
export default Header;
Hamburger.jsx
import React, { useEffect, useRef } from "react";
import gsap from "gsap";
import Link from "next/link";
const Hamburger = ({ state }) => {
//Variables for animated nodes
let menu = useRef(null);
let revealMenu = useRef(null);
let revealMenuBackground = useRef(null);
let serviceBackground = useRef(null);
let line1 = useRef(null);
let line2 = useRef(null);
let line3 = useRef(null);
let info = useRef(null);
useEffect(() => {
if (state.clicked === false) {
// close the menu
gsap.to([revealMenu, revealMenuBackground], {
duration: 0.8,
height: 0,
ease: "power3.inOut",
stagger: {
amount: 0.07,
},
});
gsap.to(menu, {
duration: 1,
css: { display: "none" },
});
} else if (
state.clicked === true ||
(state.clicked === true && state.initial === null)
) {
// open the menu
gsap.to(menu, {
duration: 0,
css: { display: "block" },
});
gsap.to([revealMenuBackground, revealMenu], {
duration: 0,
opacity: 1,
height: "100%",
});
staggerReveal(revealMenuBackground, revealMenu);
fadeInUp(info);
staggerText(line1, line2, line3);
}
}, [state]);
const staggerReveal = (node1, node2) => {
gsap.from([node1, node2], {
duration: 0.8,
height: 0,
transformOrigin: "right top",
skewY: 2,
ease: "power3.inOut",
stagger: {
amount: 0.1,
},
});
};
const fadeInUp = (node) => {
gsap.from(node, {
y: 60,
duration: 1,
delay: 0.1,
opacity: 0,
ease: "power3.inOut",
stagger: {
amount: 0.1,
},
});
};
const staggerText = (node1, node2, node3) => {
gsap.from([node1, node2, node3], {
duration: 0.8,
y: 100,
height: 0,
delay: 0.1,
ease: "power3.inOut",
stagger: {
amount: 0.3,
},
});
};
const handleService = (service) => {
gsap.to(serviceBackground, {
duration: 0,
background: `url(${service}) center center`,
});
gsap.to(serviceBackground, {
duration: 0.4,
opacity: 1,
ease: "power3.inOut",
});
gsap.from(serviceBackground, {
duration: 0.4,
skewY: 2,
transformOrigin: "right top",
});
};
const handleServiceReturn = () => {
gsap.to(serviceBackground, {
duration: 0.4,
opacity: 0,
});
};
const handleHover = (e) => {
gsap.to(e.target, {
duration: 0.3,
y: 3,
skewX: 4,
ease: "power3.inOut",
});
};
const handleHoverExit = (e) => {
gsap.to(e.target, {
duration: 0.3,
y: -3,
skewX: 0,
ease: "power3.inOut",
});
};
return (
<div
ref={(el) => (menu = el)}
className="fixed inset-0 z-10 hidden w-full h-full"
>
<div
ref={(el) => (revealMenuBackground = el)}
className="fixed inset-0 w-full h-full bg-black -z-10"
></div>
<div
ref={(el) => (revealMenu = el)}
className="relative h-full overflow-hidden bg-accentedPink"
>
<div
ref={(el) => (serviceBackground = el)}
className="absolute inset-0 w-full h-full bg-no-repeat bg-cover opacity-0"
></div>
<div className="w-full mx-auto my-0">
<div className="px-12 py-0">
<div className="relative flex items-center justify-between top-52">
<nav className="block">
<ul className="p-0 m-0">
<li className="relative h-32 overflow-hidden font-bold list-none cursor-pointer text-8xl w-160">
<Link
onMouseEnter={(e) => handleHover(e)}
onMouseOut={(e) => handleHoverExit(e)}
ref={(el) => (line1 = el)}
to="/"
>
Opportunities
</Link>
</li>
<li>
<Link
onMouseEnter={(e) => handleHover(e)}
onMouseOut={(e) => handleHoverExit(e)}
ref={(el) => (line2 = el)}
to="/"
>
Solutions
</Link>
</li>
<li>
<Link
onMouseEnter={(e) => handleHover(e)}
onMouseOut={(e) => handleHoverExit(e)}
ref={(el) => (line3 = el)}
to="/"
>
Contact Us
</Link>
</li>
</ul>
</nav>
<div ref={(el) => (info = el)} className="info">
<h3>Our Promise</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
</div>
<div className="locations">
Location:
{cities.map((el) => (
<span
key={el.name}
onMouseEnter={() => handleService(el.image)}
onMouseOut={handleServiceReturn}
>
{el.name}
</span>
))}
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default Hamburger;