The art of selecting elements and attaching event listeners in a React environment

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>
);

Answer №1

  • Try setting the active link Id to state and render based on that, instead of directly adding/removing the active class. This will prevent React from potentially overwriting your classes during rendering.

  • Avoid using the load event listener; simply call navbarlinksActive() as the window is already loaded by the time your effect is triggered.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error encountered: TypeError - The function formData.set is not supported. Unable to resolve this issue

Whenever I try to update the blog, an error occurs after reloading the browser. This error gets resolved when I refresh the browser before updating the blog. I have used formData.set in handleToggle and handleTagsToggle and it works fine there. However, ...

My navigation menu has a nested ul, but on mobile devices, it doesn't display all the items in the list. What could be causing

When I click on "Products" in my main navigation, only the first 6 items are displayed from a nested ul. How can I make all of them display when the user clicks on "Products"? Is this a CSS issue or a problem with the script? Here's a screenshot for r ...

Is there a way to simulate a click event within a Jasmine unit test specifically for an Angular Directive?

During the implementation of my directive's link function: $document.on('click.sortColumnList', function () { viewToggleController.closeSortColumnList(); scope.$apply(); }); While creating my unit test using Jasmine: describe(&apo ...

What is a way to center content vertically without using extra containers?

I've been facing challenges in vertically aligning an item within its container. Despite trying multiple suggestions that advise wrapping the content in another div or container, I encountered various issues which I won't delve into. Therefore, ...

Using the same `node_modules` folder for multiple React applications

I've configured React using NodeJS following the instructions on this link As I dive deeper into learning React, I find myself working on multiple small projects. Utilizing create-react-app has its drawbacks: It takes time to create a new app (even ...

Post Request to Express API does not produce any output

Today, I encountered an issue while trying to create a JWT authentication API in Express. When I send a POST request with Postman, it only returns {}. Below is the code for server.js: const express = require("express"); const mongoose = require("mongoos ...

Enhancing list item appearance by replacing bullets with Font Awesome icons

I need to create a list similar to this example https://i.sstatic.net/w84xS.png Although I successfully replaced the bullet with a fontawesome icon, the result is not quite right as shown here https://i.sstatic.net/yqnbJ.png You may notice a difference ...

Error encountered while attempting to convert CSV file: InvalidStateError

I've implemented a JavaScript function to be triggered by the 'onclick' event of an HTML button: function exportReportData2() { if ($("#Report").val() != "") { var screenParametersList = buildScreenParameters(); var ...

Unexpected addition of values to a list occurs when scrolling through a web element using Selenium

Having recently delved into Python, as well as programming in general, I am eager to extract data from a webelement that updates dynamically with scrolling using Selenium. A particular post on Stack Overflow titled Trying to use Python and Selenium to scro ...

Numerous references embedded within a Vue.js component

I am currently working with multiple instances of a polygonCrop component in Vue.js, each one having a unique reference to a canvas property. These components are utilized in separate crop functions triggered by button clicks. My question is how to effecti ...

Does IE 9 support Display Tag?

Although this may not be directly related to programming, I have been unable to locate any information regarding the compatibility of IE 9 or even 8 with the Display Tag Library. The documentation is silent on the matter. If anyone has encountered any cha ...

"Padding has not been recognized as a valid input value

I'm struggling with getting padding to be accepted by the browser when I style a card using Material-UI. const useStyles = makeStyles((theme) => ({ cardGrid: { padding: '20px auto' }, })) Unfortunately, the browser is not recogni ...

Can someone help me troubleshoot why my setState function isn't functioning properly?

class SurveyForm extends Component { constructor(props) { super(props); this.nameInput = React.createRef(); this.state={ uid:uuid.v1(), studentName:'', isSubmitted:false } nameSubmit=(e)=> { let name = this.nameInput.current.value; console.log ...

The Reactjs router appears to be failing to render any components

webpack.config.js module.exports = { entry: { app: __dirname + '/src/index.js' }, output: { path: __dirname + '/public', filename: 'bundle.js' }, mode: 'development', devS ...

Filtering records by a joined association in Rails using Ajax

My goal is to enable an end user to filter a data grid based on an associated record. The data grid currently displays a list of Activities: The model for activity.rb (the list of records) class Activity < ApplicationRecord belongs_to :student ...

Inheriting Internet Explorer's zoom level within the WPF web browser control

My WPF window hosts a web browser control for displaying html/css pages, but I'm running into issues with the zoom factor from Internet Explorer. The web browser control seems to be affected by IE's zoom level, causing distortion in the way my HT ...

Is an Ajax powered loading feature used in transitions between pages?

I recently came across this interesting website: It appears that they have implemented a clever technique where new content is dynamically loaded using AJAX, giving the impression of seamless navigation. Additionally, they have succeeded in hiding the bro ...

Displaying image while processing substantial ajax data

I implemented code to toggle the display of a loading image on my web page while making ajax requests. $(document).ajaxStart(function(){ $("#please_wait").css("display","block"); }); $(document).ajaxComplete(function(){ $("#please_wait").css(" ...

Can you tell me the CSS equivalent of the SASS/SCSS expression "&$"?

Hey there! I've been diving into the world of Material-UI components and stumbled upon this interesting styling snippet: root: (0, _extends3.default)({}, theme.typography.subheading, { height: theme.spacing.unit * 3, boxSizing: 'content- ...

Why isn't data coming through after sending ajax post requests?

Why am I unable to retrieve data after sending AJAX post requests? During the process of sending an AJAX post request, I use $('#fid1 input,select').attr('disabled','disbaled'); to disable form inputs and then, after a suc ...