What is the best way to utilize the forEach method in React to manipulate a navigation element containing multiple links?

Here is the code I'm trying to convert:

  document.addEventListener("scroll", function() {
  const links = document.querySelectorAll(".nav-link");
  for (const l of links) l.classList.toggle('scrolling', window.scrollY > 0);
})

I want to change the color of all my links when the page is scrolling. Using an if-else statement would only change the color of the first link, so a forEach statement seems more appropriate.

The code above was converted to React like this:

const [isLinkScrolling, setIsLinkScrolling] = useState(false);

const handleLinkScroll = () => {
   for (const l of links) {
      l.classList.toggle('scrolling', window.scrollY > 0);
   }
};

useEffect(() => {

    document.addEventListener('scroll', handleLinkScroll);

    return () => { 
        document.removeEventListener('scroll', handleLinkScroll);  
    };

}, []);

return (

<ul className={`nav_links ${isNavShowing ? "show_nav" : "hide_nav"}`}>
{
    links.map(({name, path }, index) => {
        return (
            <li key={index}>
                <NavLink to={path} className={({isActive}) => isActive ? "active-nav" : ""}  onClick={() => setIsNavShowing(prev => !prev)}>{name}</NavLink>
            </li>
        )   
    })
}
</ul>

)

However, there seems to be an error here:

setIsLinkScrolling(
   for (const l of links) l.classList.toggle( window.scrollY > 0);
);

I haven't been able to figure out this error yet.

Answer №1

It's not recommended to pass the setIsLinkScrol setter to addEventListener as it will set the entire Event to the state, which is unnecessary in this case.

Instead, create an onScoll function that will call setState with window.scrollY.

Then you can apply a className to specific element(s) based on whether the scollValue > 0


Check out this small demo:

const { useState, useEffect } = React;

const Example = () => {

    const [scrollValue, setScrollValue] = useState(0);

    const onScroll = (e) => setScrollValue(window.scrollY);

    useEffect(() => {
        document.addEventListener('scroll', onScroll);
        return () => document.removeEventListener('scroll', onScroll);
    }, [])

    return (
        <div>
            <h1>{'Example'}</h1>
            {[...Array(50)].map((e, i) => (
                <span className={scrollValue > 0 ? 'scrolling' : ''} key={i}>Some content</span>
            ))}
        </div>
    )
}
ReactDOM.render(<Example />, document.getElementById("react"));
div { display: flex; flex-direction: column }
.scrolling { color: orange; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>


{[...Array(50)].map((e, i) => (
    <span className={scrollValue > 0 ? 'scrolling' : ''} key={i}>Some content</span>
))}

Here I'm using [...Array(50)].map to repeat the same element 50 times
How to repeat an element n times using JSX and Lodash

Then we utilize a Conditional (ternary) Operator to assign the class conditionally.

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

storing information in localStorage using react-big-calendar

Incorporating react-big-calendar into my project, I encountered a problem where the events in the calendar would disappear upon page refresh despite saving them in localStorage. I had planned to store the events using localStorage and retrieve them later, ...

Retrieve an array from a JSON object by accessing the corresponding key/value pair using the utility library underscore

I have a dataset in JSON format (as shown below) and I am attempting to use the _.where method to extract specific values from within the dataset. JSON File "data": [{ "singles_ranking": [116], "matches_lost": ["90"], "singles_high_rank": [79 ...

Establishing a state variable in react-dropzone `onDrop` function, following the extraction of data using exceljs

When it comes to a use case: A user drops a file The file is read using exceljs The values from a column are extracted and stored in an array ids The state variable onDropIds should be set with the contents of ids. Steps 1-3 are working fine, but I'm ...

"Encountered an issue with Next-Auth session returning as undefined in getServerSideProps using NextJS version 13.2

When inspecting the code below, session is found to be undefined upon logging from the client side after being transferred from getServerSideProps. import { getServerSession } from 'next-auth/next'; import { authOptions } from './api/auth/[. ...

Confused about having to use window.variableName in my code and not understanding the reason

Working on a web app with JS, Angular, and Meteor that integrates the Youtube API has been quite challenging. In one of my controllers, I initialized the youtube player object in the constructor following the necessary steps outlined by the Youtube API. Ho ...

converting HTML values to TypeScript

I'm a beginner with Angular and could use some assistance. Currently, I have two components - one for the index and another for navigation. Within the index component, there are subcomponents that change based on the value of a variable called produ ...

Improved efficiency in CSS for left transition animations

Here is the current code I am using: .s2 { top: 150px; left: 20px; position: absolute; transition: left 300ms linear; } I am currently updating the left position dynamically using JavaScript based on scroll events. However, I have noticed that th ...

What is the method for rendering an ejs template from express using fetch without the need to submit a form?

login.js file: const form = document.getElementById('loginForm'); form.addEventListener('submit',async(e)=>{ e.preventDefault(); return await fetch(`localhost:8000/route`, { method: "get", heade ...

How can I replicate the functionality of the span element using Javascript?

Using Javascript, I am able to display a paragraph without the need for HTML. By adding it to an HTML id, I can manipulate individual words within the text. My goal is to make specific words cursive while keeping the entire paragraph in its original font s ...

Document: include checksum in HTML

I have a set of three files. The file named loader.js is responsible for creating an iframe that loads another file called content.html, which in turn loads content.js. I have made loader.js publicly available so that other users can include it on their ow ...

Tips for avoiding the push method from replacing my items within an array?

Currently, I am diving into Typescript and VueJS, where I encountered an issue with pushing elements to my array. It seems to constantly override the 'name' property. Let me share the code snippet causing this problem: const itemsSelectedOptions ...

Getting rid of an Ajax loader graphic after a period of time

After a button is clicked, I have an ajax loader that appears and here is the code snippet: jQuery(document).ready(function($) { $('#form').on('submit', function() { $('#submit').css('display', 'bl ...

Challenge encountered when rendering markdown in NextJS/React

Having trouble rendering markdown in NextJS/React again. Here's the code I'm using: import ReactMarkdown from "react-markdown"; import gfm from 'remark-gfm'; const PostContent = () => { const source = ` # Hello, ...

Tips for transitioning your functions into class-based components on React

Looking for guidance on how to convert my function-based components to class-based components. Here's the original function-based component: import React, { useEffect, useState } from "react" import ReactMapGL, { Marker, Popup } from "r ...

Utilize Angular 5 to implement URL routing by clicking a button, while also preserving the querystring parameters within the URL

I have a link that looks like this http://localhost:4200/cr/hearings?UserID=61644&AppID=15&AppGroupID=118&SelectedCaseID=13585783&SelectedRoleID=0 The router module is set up to display content based on the above URL structure { path: & ...

What causes the Invalid Form Body error to appear when using the Discord API?

While developing a Discord bot, I encountered an issue with creating a ping command. The error message received was as follows: (node:37584) UnhandledPromiseRejectionWarning: DiscordAPIError: Invalid Form Body embed.footer.icon_url: Scheme "flashybot& ...

Is there a way to extract only the value from the most recent request?

While working with VueJS, I have a handler for changes in an input field that looks like this: inputHandler(url, params){ const p = new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('POST&ap ...

Attempting to output numerical values using Jquery, however instead of integer values, I am met with [Object object]

I am struggling to figure out how to display the value contained in my object after attempting to create a Calendar using Jquery. I attempted to use JSON.toString() on my table data, but it didn't solve the issue. Perhaps I am not placing the toString ...

Show only child elements of a specific type within the parent div

Looking to identify divs with the class 'test' that contain only buttons in their child nodes. This is the HTML code that needs to be filtered. <div class="test"> <div> <button> <span>Button 1</span></butto ...

Effortlessly sending multiple forms on a single page via POST in Express JS without the need for page refresh

I am creating a new application using ExpressJS and I want to include the following HTML code in a jade file. On one of my pages, I have 4 form buttons: <div class="dog"> <div class="dog_wrapper clearfix"> <div cla ...