Currently, I am working on my portfolio website using Gatsby. The layout includes a sidebar on the left with navigational links (Home, About, Work, etc.), and the main content is displayed as one long strip of sections on the right. When a user clicks on a link, the page smoothly scrolls to the corresponding section. My goal is to apply a different style to the link when the user reaches that particular section. While I have successfully implemented a solution using vanilla JavaScript to achieve this active state functionality, I am now exploring how to accomplish the same in a more React-friendly manner.
useEffect(() => {
const navbarlinks = document.querySelectorAll("nav a");
const navbarlinksActive = () => {
let position = window.scrollY + 200;
navbarlinks.forEach((navbarlink) => {
let section = document.querySelector(navbarlink.hash);
if (position >= section.offsetTop && position <= section.offsetTop + section.offsetHeight) {
navbarlink.classList.add("active");
} else {
navbarlink.classList.remove("active");
}
});
};
window.addEventListener("load", navbarlinksActive);
document.addEventListener("scroll", navbarlinksActive);
return () => {
window.removeEventListener("load", navbarlinksActive);
document.removeEventListener("scroll", navbarlinksActive);
};
}, []);
In the code snippet above, I first select all navigation links. Then, by iterating through them, I retrieve the hash property, which corresponds to the id of the respective section being targeted. Depending on the position, the CSS class is either added or removed. This script resides within the sidebar component, where the links are Gatsby Link elements.
return (
<nav>
<Link
className="hover:text-clr-accent flex items-center py-2 px-4 transition"
to="#home"
>
<i className="fa-solid fa-house w-6 text-center text-lg"></i>
<span className="pl-2 text-lg">Home</span>
</Link>
<Link
className="hover:text-clr-accent flex items-center py-2 px-4 transition"
to="#resume"
>
<i className="fa-solid fa-file w-6 text-center text-lg"></i>
<span className="pl-2 text-lg">Resume</span>
</Link>
<Link
className="hover:text-clr-accent flex items-center py-2 px-4 transition"
to="#about"
>
<i className="fa-solid fa-address-card w-6 text-center text-lg"></i>
<span className="pl-2 text-lg">About me</span>
</Link>
<Link
className="hover:text-clr-accent flex items-center py-2 px-4 transition"
to="#work"
>
<i className="fa-solid fa-briefcase w-6 text-center text-lg"></i>
<span className="pl-2 text-lg">My work</span>
</Link>
</nav>
);