How to efficiently highlight a row in a table when hovering over one of its cells, utilizing the React hook useState

I have a table displaying a list with three columns: item, delete-button-1, delete-button-2. When hovering over a delete button, the corresponding item is highlighted in red.

Utilizing React Hook useState to store the index of the row where the delete button is hovered.

I have two delete button implementations, differing only in the onClick attribute, both encountering issues.


Delete Button: Implementation 1

  1. Add items to the list
  2. Delete all items
  3. Add new items to the list

The issue is that the first item in the new list is highlighted in red, persisting until a delete button is hovered.


Delete Button: Implementation 2

  1. Add items to the list
  2. Delete an item

The problem is that although the delete button of the next row replaces the deleted row's button, the item does not highlight until the delete button is re-hovered.


let id = 0
const {useState} = React

const Table = () =>{
  const [list, setList] = useState([])
  const [warningIndex, setWarning] = useState(null)

  const rows = list.map((item, index) =>{
    const rowClass = (warningIndex === index) ? "warning" : ""

    return (
      <tr key={index}>
        <td className={rowClass}>{item}</td>
        <td
          className="delete-button"
          onMouseEnter={() => setWarning(index)}
          onMouseLeave={() => setWarning(null)}
          onClick={() => setList([...list.slice(0, index), ...list.slice(index + 1)])}>
          -
        </td>
        <td
          className="delete-button"
          onMouseEnter={() => setWarning(index)}
          onMouseLeave={() => setWarning(null)}
          onClick={() =>{
            setList([...list.slice(0, index), ...list.slice(index + 1)])
            setWarning(null)
          }}>
          -
        </td>
      </tr>
    )
  })

  return (
    <table>
      <tbody>
      <tr>
        <td
          className="add-button"
          colSpan="3"
          onClick={() => setList([...list, id++])}>
          +
        </td>
      </tr>
      {rows}
      </tbody>
    </table>
  )
}

ReactDOM.render(<Table/>, document.getElementById('root'));
table {
  width: 200px;
  border-collapse: collapse;
}

td {
  padding: 4px 8px;
  border: 1px solid lightgrey;
}

td.add-button, td.delete-button {
  cursor: pointer;
  width: 1%;
}

td.add-button:hover {
  background-color: lightgrey;
}

td.add-button:active {
  background-color: darkgrey;
}

td.delete-button:hover {
  background-color: #ffcdd2;
}

td.delete-button:active, td.warning {
  background-color: #ef9a9a;
}
<script <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

I am seeking a delete button implementation that addresses these issues. I've attempted two, but neither solves the problems.

Answer №1

When mapping in React and using index as the key, it can potentially lead to issues, especially when adding or removing components.

  return (
      <tr key={index}>

Consider using a unique key to resolve this problem. You can find more information on React keys here.

Answer №2

What are your thoughts on this solution? Make sure to verify if the list is empty. =)

let id = 0
const {useState} = React

const Table = () => {
  const [list, setList] = useState([])
  const [warningIndex, setWarning] = useState(null)

  const rows = list.map((item, index) => {
    const rowClass = (warningIndex === index) ? "warning" : ""

    return (
      <tr key={index}>
        <td className={rowClass}>{item} - index: {index}</td>
        <td
          className="delete-button"
          onMouseEnter={() => setWarning(index)}
          onMouseLeave={() => setWarning(null)}
          onClick={() => {
            const newList = [...list.slice(0, index), ...list.slice(index + 1)]
            if (newList.length === 0){
              setWarning(null)
              }
            setList(newList)
           }}>
          -
        </td>
      </tr>
    )
  })

  return (
    <table>
      <tbody>
      <tr>
        <td
          className="add-button"
          colSpan="3"
          onClick={() => setList([...list, id++])}>
          +
        </td>
      </tr>
      {rows}
      </tbody>
    </table>
  )
}

ReactDOM.render(<Table/>, document.getElementById('root'));
table {
  width: 200px;
  border-collapse: collapse;
}

td {
  padding: 4px 8px;
  border: 1px solid lightgrey;
}

td.add-button, td.delete-button {
  cursor: pointer;
  width: 1%;
}

td.add-button:hover {
  background-color: lightgrey;
}

td.add-button:active {
  background-color: darkgrey;
}

td.delete-button:hover {
  background-color: #ffcdd2;
}

td.delete-button:active, td.warning {
  background-color: #ef9a9a;
}
<script <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

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

What is the method for showcasing background images sequentially?

css code #intro { position: relative; background-attachment: fixed; background-repeat: no-repeat; background-position: center top; -webkit-background-size: cover; -moz-background-size: cover; backgr ...

Divide a string within a JSON object and output it as an array

I've encountered a challenge while working with data received from an API. My goal is to loop through this information and generate HTML elements based on it. The issue lies in the 'subjects' data, which arrives as a string but needs to be m ...

What could be the reason for parent props not updating in child components in VueJS?

Hello, I am new to VueJS and encountering an issue. In the main.js file, I am passing the user variable to App.vue using props. Initially, its value is {} The getLoginStatus() method in main.js monitors the firebase authentication status, and when a user ...

Display the message "Please complete this selection" for the Radio Field in the HTML form

I am facing an issue with error message display in my form. The text input field shows a nice message saying "Fill out this field", but the Radio and Dropdown fields do not show any error messages when left empty. How can I ensure that error messages are ...

What techniques can I use to modify an object while it's being iterated through?

I've been attempting to manipulate the object while looping through it, but unfortunately, it's not working. How can I modify it so that the constant patient includes the property lastActivity inside the this.model array? My code looks like this ...

Analyzing objects within an array for similarities

Suppose I have an array containing objects: var arr = [ { id: 1, pt: 0 }, { id: 2, pt: 12 }, { id: 3, pt: 7 }, { id: 4, pt: 45 }, { id: 5, pt: 123 }, ]; I am looking to loop through this array (possibly using array.forEach or array.map) ...

Changing the time zone of a browser using JavaScript or jQuery

After researching numerous discussions on the topic, it appears that changing the browser's timezone programmatically is not possible. Although the moment-timezone.js library allows us to set timezone for its objects, it does not affect the browser&ap ...

not getting any notifications from PHP

Despite receiving a status of '1' from this process file, my JavaScript code seems to be working fine. However, I am facing an issue with not receiving the email. <?php //Retrieve form data. //GET - user submitted data using AJAX //POST - in ...

Is it possible to incorporate an external javascript file in my CSS file?

Currently, I am attempting to create a setup where my background adjusts based on the width of the user's browser. However, I am constrained by a background specified in the external stylesheet under a specific element. While I have the ability to alt ...

Arrange a div element within another div by utilizing the fixed positioning property, while also accounting for any potential "white space

Can someone help me figure this out: I currently have this much progress: http://jsbin.com/apikiw/3/edit#preview The issue I'm facing is that I am unable to insert it between the <p /> tags due to its dynamic nature... any solutions or suggest ...

Nodemailer is failing to send emails on Heroku

Recently, I encountered an issue that has been puzzling me. I use cloud9 for work and nodemailer works perfectly fine, sending all emails from a form I created. However, when I deployed a small server to Heroku with just a change in an environmental vari ...

What is the best way to incorporate a browser-specific vanilla JS library with dependencies into a React application?

Looking for a js/reactjs solution to interact with a janus webrtc gateway? I've decided to utilize the janus.js library from the meetecho janus-gateway sourcecode because: A: This library checks browser compatibility with Janus. B: The core team main ...

Deciphering the Cause of mapStateToPropsCall in Redux and React

When handling an unsuccessful http call resulting in an error message being displayed, I encounter subsequent state changes triggering multiple render calls. Is there a technique to identify the cause of these state changes and mapStateToProps calls? Alter ...

Having trouble making an HTML5 video work on Android? It seems to play fine when clicking the play button,

It has come to my attention that html5 video on Android devices is unable to autoplay. Currently, the video only plays on the device when the user manually clicks on the play button. <video width="640px" height="360px" src="media/video/Moments_of_Every ...

Obtaining data attributes in Angular 8

I'm working with Angular 8 and I came across an issue. In my code snippet, there are two data attributes assigned to a button element, but only one attribute is showing up. Is this a syntax error or a bug? <button [attr.data-popolamento]="all" [a ...

How to use Javascript to pause an HTML5 video when closed

I am new to coding and currently working on a project in Adobe Edge Animate. I have managed to create a return button that allows users to close out of a video and go back to the main menu. However, I am facing an issue where the video audio continues to p ...

Automating the click of JavaScript buttons with Selenium

Test page Experimenting with the above Indeed link to test my selenium automation skills. I am attempting to automate the clicking of the 'apply' button using the Firefox webdriver. My code snippet is as follows: from selenium import webdriver ...

What is the best way to keep the footer at the bottom and make it fixed in Material UI?

import * as React from "react"; import Container from "@mui/material/Container"; import Image from "next/image"; import Link from "@/src/Link"; import Box from "@mui/material/Box"; import Typography from &q ...

What is the best method for implementing a "night mode" feature using CSS?

I have a vision for a website that offers both a 'day' and 'night mode', providing users with a light and dark version of the site. However, I'm struggling to find the best way to achieve this. Initially, I attempted creating two ...

Enhancing the basic Error class through hooking and monkey-patching

Is there a way to customize the behavior of the Error class in JavaScript? I need to replace it with a custom class that adds additional fields and logic whenever someone tries to throw an error or any subclass of Error in my code base. This kind of custo ...