When working with ReactJs, you may encounter a delay in adding a class to the li element upon click event

I am facing an issue where the first li element works perfectly when clicked, but for the rest of the elements, I have to click twice to apply the desired styling. Can anyone explain why this behavior is occurring?

App.js

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  state={
    clicked: false,
    index: 0,
    arr: ['a','b','c','d','e','f','g','h']
  }

  handleClick = (i) => {

    this.setState({
      clicked: !this.state.clicked,
      index: i
    });

  }
  render() {
    console.log(this.state.index);
    return (
      <div className='App'>
         <ul>
           {
             this.state.arr.map((el, i) => (
             <li key={i} className={(this.state.clicked && this.state.index === i) ? 'clicked':''} 
                  onClick={() => this.handleClick(i)}>{el}</li>
             ))
           }
         </ul>
      </div>
    )
  }
}
export default App;

App.css

.App {
  text-align: center;
  width: 60vw;
  margin: 50px auto;
  border: 1px solid grey;
}

ul{
  list-style: none;
}

li{
  padding: 4px 7px;
  border: 1px solid grey;
  margin-bottom: 15px;
  text-align: left;
  width: 50%;
  cursor: pointer;
}

.clicked{
  background: #000;
  color: white;
}

The issue lies in applying the clicked class programmatically through CSS. Can someone point out what might be missing in my implementation?

Answer №1

Update:

In retrospect, I've come to realize that we are constantly resetting the value of clicked with each click. It should remain true after the initial click.

class App extends React.Component {
  state={
    clicked: false,
    index: 0,
    arr: ['a','b','c','d','e','f','g','h']
  }

  handleClick = (i) => {
    this.setState(state => ({
      clicked: true,
      index: i
    }));
  }
  
  render() {
    const shouldAddClassName = this.state.clicked === true;
    const currentIndex = this.state.index;
    console.log('currentIndex', currentIndex);
    return (
      <div className='App'>
         <ul>
           {
             this.state.arr.map((el, i) => (
             <li key={i} className={(shouldAddClassName && currentIndex === i) ? 'clicked': ''} 
                  onClick={() => this.handleClick(i)}>{el}</li>
             ))
           }
         </ul>
      </div>
    )
  }
}

ReactDOM.render(<App /> , document.querySelector('#app'));
.App {
  text-align: center;
  width: 60vw;
  margin: 50px auto;
  border: 1px solid grey;
}

ul {
  list-style: none;
}

li {
  padding: 4px 7px;
  border: 1px solid grey;
  margin-bottom: 15px;
  text-align: left;
  width: 50%;
  cursor: pointer;
}

.clicked {
  background: #000;
  color: white;
}
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="app"></div>

Answer №2

To solve the issue with double clicking, insert the following code inside the handleClick() function:

handleClick = (i) => { this.setState({ clicked: true, index: i }); } By setting clicked to true, you can instantly apply a class to each li element, effectively resolving the double click problem.

I trust this solution will be beneficial for you.

Answer №3

Here is a revised version of the handleClick function that should solve your issue:

  handleClick = (i) => {
    this.setState({ clicked: false }, () => {
      this.setState({
        clicked: true,
        index: i
      });
    })
  }

Your current code isn't functioning properly because it allows for double clicking to add the clicked class. The first click should remove the clicked class from the already active element, while the second click should activate the new clicked class.

I believe this updated function will address your concerns.

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

Fine-tuning the flexbox grid layout for various screen sizes, both big and small

Two different layouts were created. The first layout is designed for medium & large screens, while the second one is tailored for devices with a maximum width of 736px. Check out the vanilla implementation using flexbox (without mobile adaptation) Here ...

The Hidden Div containing NicEdit is now shrunk down to a smaller size

Attempting to integrate the NicEdit editor for a hidden textarea stored within a div has presented some challenges. The goal is for the targeted textarea's parent div to be revealed upon the user clicking a button, with the textarea's width set t ...

Ways to incorporate onload animation into a Pie chart with billboard js

I am currently working on implementing a pie chart with animation using billboard js. However, I am facing difficulties in applying the onload animation. Can anyone provide guidance on how to achieve this? For reference, you can view an example of the des ...

CSS alert problem encountered

I have an HTML and CSS notification template that I would like to incorporate into my PHP code. You can view the template here. HTML <div class="alert-box error"><span>error: </span>Write your error message here.</div> &l ...

Can someone explain how to unpopulate in Mongoose?

Currently utilizing autopopulate, I have encountered a specific scenario where I do not wish to populate. How can I unpopulate in this situation? var userSchema = new Schema({ local: { type: ObjectId, ref: 'Local', autopopulate: true }, face ...

The art of simulating a service in unit tests for an AngularAMD application

I am working on an angular application using AngularAMD with require.js. I need to simulate a service as shown below: module(function ($provide) { $provide.service('ToolsService', function () { var toolsServiceMock = { som ...

Content not being hidden by Twitter Bootstrap tabs

I am encountering an issue with my code. When I click on an inactive tab, the content of the first tab does not hide and both tabs' content is displayed simultaneously. Is there a solution to this problem? Thank you for your help! <ul style="l ...

JavaScript: A dynamic table is created with columns populated by JSON data. The row structure is compromised

On my webpage, I pull in two sets of JSON data: 1) warehouses and 2) items. After receiving an Ajax search response from my view, I need to dynamically generate the TDs of a table based on the warehouses information. The goal is to populate all TDs for ev ...

Use CSS media queries to swap out the map for an embedded image

Looking to make a change on my index page - swapping out a long Google Map for an embedded image version on mobile. The map displays fine on desktop, but on mobile it's too lengthy and makes scrolling difficult. I already adjusted the JS setting to "s ...

Guide on validating an Australian phone number with the HTML pattern

When it comes to PHP, I have found it quite simple to validate Australian phone numbers from input using PHP Regex. Here is the regex pattern I am currently using: /^\({0,1}((0|\+61)(2|4|3|7|8)){0,1}\){0,1}(\ |-){0,1}[0-9]{2}(\ | ...

Applying a CSS class to a jeditable input field

Is there a way to apply a simple class tag to a jeditable input field? The developer's instructions on their website () suggest using the following code snippet under "How to style elements?": $('.editable').editable('http://www.exampl ...

The function window.require does not exist

Here is the code I wrote: const { ipcRenderer } = window.require('electron'); An error occurred: TypeError: window.require is not a function I attempted to utilize IPC communication in order to manage the Electron window using React. Regrett ...

Utilizing various colors for tooltipFontColor in Chart.js

I'm trying to customize the font color for tooltip labels in Chart.js, but I want to set different colors based on certain conditions. Specifically, I want the label color to be white by default, but change to red if a condition is met. I've look ...

What could be causing the ReferenceError: self is not defined issue I'm encountering as I try to import a client-side library?

Having trouble creating a custom xterm react component within Next.js, I'm currently stuck on an unfamiliar error message. I am attempting to import a client-side npm module named xterm, but whenever I include the import line, the application crashes ...

Issue encountered when attempting to add multiple JavaScript functions through Greasemonkey using unsafeWindow

One issue that arises is that the functions are unable to recognize each other. For example: unsafeWindow.helloworld = function() { alert('Hello world!'); helloworld2(); // this fails with an error indicating it does not exist } unsa ...

How can I dynamically update a div without refreshing the page by using an onclick event on a

When working on my project, I found helpful insights from this Stack Overflow thread. The structure of template-comparison.php involves fetching code from header.php to ensure the page displays properly. However, the actual "fetch code" process remains un ...

Tips on elevating a dragged div above all other elements when utilizing two scrollbars

Currently, I have two horizontal scrollers where I need to drag a div from the upper scroller to the lower scroller. While this functionality is working properly, there is an issue with the dragged div getting lost under the borders of the scroller during ...

Apply jQuery styling to new select box on page in order to maintain consistent styling throughout

I've encountered an issue with my jQuery select box styling. It appears to work perfectly on the initial page load, but when new content containing a select box is dynamically loaded onto the page, the styling doesn't get applied to it. Can anyo ...

Having difficulty navigating between Spring MVC and Angular Js components in my project

https://i.sstatic.net/Iovci.png I am currently facing an issue with my project structure. I received a "Failed to load resource: the server responded with a status of 404 ()" error message, indicating that ShowDetail.jsp is not found. Can anyone advise on ...

Is there a way to implement a "report" button for sending messages that doesn't require using email?

I am in need of a button that reads "Report a typo" and alerts me when it is clicked on a specific page. The project I am working on consists of multiple short pages with just a few paragraphs in each HTML template. It would be helpful for me to have a way ...