What is the best way to delete a CSS class from a specific element in a list using React?

I need to implement a functionality in React that removes a specific CSS class from an item when clicking on that item's button, triggering the appearance of a menu. Here is my code snippet.

import "./Homepage.css"
import React, { useState, useEffect, useRef } from "react"
// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
// import { faArrowDown } from "@fortawesome/free-solid-svg-icons"
import { Link } from "react-router-dom"
import useFetch from "./useFetch"
import Axios from "axios"

export default function Homepage() {
  const [body, setBody] = useState("")
  const [sortedData, setSortedData] = useState("")
  const [data, setData] = useState("")
  const [css, setCss] = useState("")
  const [flash, setFlash] = useState(null)
  const posts = useFetch("http://localhost:5000/api/data")
  const firstRender = useRef(true)

  useEffect(() => {
    let test = JSON.parse(window.localStorage.getItem("user"))
    console.log(test)
    setData(posts)
  }, [posts])

  useEffect(() => {
    if (firstRender.current) {
      firstRender.current = false
      return
    }
    data.sort(function (a, b) {
      return new Date(b.date) - new Date(a.date)
    })
    setSortedData(data)
  }, [data])

  const handleSubmit = (e) => {
    e.preventDefault()
    Axios.post("http://localhost:5000/api/react-create-post", { text: body }, { withCredentials: true })
      .then((res) => {
        setSortedData((prevArray) => [res.data.post, ...prevArray])
        setFlash("Successfully created post.")
        setCss("success-msg")
        setBody("")
      })
      .catch((err) => {
        setCss("error-msg")
        setFlash("Field cannot be left blank.")
      })
  }

  const handleClick = (e) => {
    e.preventDefault()
    e.target.parentElement.children[1]
  }

  return (
    <div>
      <center>
        <div className="create-container">
          <div className="posts-title">Create Post</div>
          <form id="theForm" onSubmit={(e) => handleSubmit(e)}>
            <textarea onChange={(e) => setBody(e.target.value)} value={`${body}`} id="theInput" className="post-input" name="text" type="text"></textarea>
            <button className="submit-btn">POST</button>
          </form>
        </div>
        <div id="postsContainer" className="posts-container">
          <div className="posts-title">Latest Posts</div>
          {flash ? <div className={css}>{flash}</div> : console.log()}
          <div id="postInput">
            {sortedData &&
              sortedData.map((item) => {
                return (
                  <div className="post-container" key={item._id}>
                    <Link className="a" to={`/user/${item.author}`}>
                      <h3 className="author">{item.author}</h3>
                    </Link>
                    <div className="date">{item.date.toLocaleString()}</div>
                    <div className="options-cont">
                      <button onClick={(e) => handleClick(e)} id="optionsBtn" className="options-btn">
                        <i className="fas fa-ellipsis-v"></i>
                      </button>
                      <button data-author={`${item.author}`} data-id={`${item._id}`} data-text={`${item.body}`} id="editBtn" className="edit inside-btn invisible">
                        Edit
                      </button>
                      <button data-author={`${item.author}`} data-id={`${item._id}`} id="deleteBtn" className="delete inside-btn invisible">
                        Delete
                      </button>
                      <br></br>
                    </div>
                    <p className="body-text">{item.body}</p>
                  </div>
                )
              })}
          </div>
        </div>
      </center>
    </div>
  )
}

In my understanding, setting the state as the className will affect all items in the "sortedData" array rather than just one item. I only want the menu for a specific item to appear.

Answer №1

According to source, the recommended approach is to create individual components for each element with their own "showing" state.

If you use state as the className, it could affect all items in the array and show menus for each one. To display the menu for only one item, a separate flag should be used for each menu, possibly tied to the item's ID.

Using a single flag in state would cause issues, so instead, utilize a set of flags, one for each menu linked to the item's ID.

If you are working with function components and hooks, the initial state setup would look like this:

const [showing, setShowing] = useState(new Set());

When rendering, assign the class based on whether the item's ID is present in the set:

<theElement className={showing.has(item._id) ? "class-to-show" : "class-to-hide" ...

For toggling, pass the item's ID to the button onClick method:

<button onClick={(e) => handleClick(e, item._id)}

Update the state accordingly inside the handleClick function:

const handleClick = (e, id) => {
    e.preventDefault()
    setShowing(showing => {
        let updatedSet = new Set(showing);
        if (updatedSet.has(id)) {
            updatedSet.delete(id);
        } else {
            updatedSet.add(id);
        }
        return updatedSet;
    });
};

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

Discovering React Styled Components Within the DOM

While working on a project using Styled Components in React, I have successfully created a component as shown below: export const Screen = styled.div({ display: "flex", }); When implementing this component in my render code, it looks like this ...

How do I disable the hover and click highlighting effect on a div in Vuetify using v-on in Vue2?

Currently, I have implemented a Vuetify VListItem in a NavigationDrawer with an on click listener that displays a menu in the div below. The menu is functioning properly - opening and closing as expected. However, it highlights on hover/click which I wou ...

Merge arrays values with Object.assign function

I have a function that returns an object where the keys are strings and the values are arrays of strings: {"myType1": ["123"]} What I want to do is merge all the results it's returning. For example, if I have: {"myType1": ["123"]} {"myType2": ["45 ...

AngularJS Partial Views: Enhancing Your Website's User Experience

As a newcomer to the world of Angular, I am seeking guidance on a specific issue. I have encountered a one-to-many relationship scenario where one Category can have multiple Product items. The challenge lies in my layout page setup where I display various ...

Is there a way to retrieve values from TextFields and Select elements by simply clicking on a button?

I am currently working on a project using react, redux, and material ui. I need to retrieve data from a TextField in order to make an order. The code snippet below showcases my current implementation: <Select value={product.color_set[0].title}> { ...

Enhancing Watermark Functionality for Text Boxes

I am encountering an issue with three textboxes all having watermarks. When I use JavaScript to set the value of the second textbox in the OnChange event of the first textbox, the text appears as a watermark. However, when I click on the textbox, it become ...

Encountered a preventDefault() error in React when trying to pass a value from a

const onSubmit = (event, val) => { console.log(val); event.preventDefault(); setValues({ ...values, error: "", success: "", key: val }); setDidSubmit(true); }; When working with React and using the map function: {d ...

Pass data in JSON format from Laravel controller to AngularJS

When working with Laravel, I successfully converted data in MySQL to JSON for use in AngularJS. However, I am now unsure of how to effectively utilize these values in AngularJS. Can anyone offer assistance? View output data (hide each value) Controller ...

JSX: dynamically include element based on condition

I am currently utilizing Bootstrap 3 and I have a requirement to clear each .row once 12 columns have been generated. However, my code is not working as expected and I encounter this error: Failed to compile. Error in ./src/File/file.js Syntax error: Unex ...

What is the best way to monitor and record the height of a div element in a React application?

Exploring the Height of a Div I am interested in monitoring the height of a div element so that I can dynamically adjust distances based on varying screen widths. The animation should respond to changes in screen width, such as when text stacks and the he ...

server running on node encountered an error due to a port that is already in use

The Server instance emitted an 'error' event at: at emitErrorNT (net.js:1340:8) at processTicksAndRejections (internal/process/task_queues.js:84:21) { code: 'EADDRINUSE', errno: 'EADDRINUSE', syscall: 'listen', addre ...

The success of your order hinges on jQuery being defined when using browserify

I encountered an issue while attempting to utilize a plugin located in /js/lib/stellar.jquery.js: var $ = require('jquery'); require('./lib/stellar.jquery') $(function(){ $.stellar(); }); Upon running the code, I received an err ...

JSON returning issue with date formatting

After converting a date to a string using ToString("d") in C# and then serializing it into JSON for the client, I'm encountering an issue where instead of displaying the formatted date on the page, I see the following literal text: /Date(-62135575200 ...

Uncovering the source of glitchy Angular Animations - could it be caused by CSS, code, or ng-directives? Plus, a bonus XKCD comic for some light-hearted humor

Just finished creating an XKCD app for a MEAN stack class I'm enrolled in, and I'm almost done with it. However, there's this annoying visual bug that's bothering me, especially with the angular animations. Here is the link to my deploy ...

Removing all repetitions from an array in JavaScript

My collection of objects includes the following inputs: var jsonArray1 = [{id:'1',name:'John'},{id:'2',name:'Smith'},{id:'3',name:'Adam'},{id:'1',name:'John'}] There is a dupl ...

Highlight react-bootstrap NavItems with a underline on scroll in React

I am currently working on a website where I have implemented a react-bootstrap navbar with several Nav items. My goal is to enable smooth scrolling through the page, where each section corresponds to an underlined NavItem in the navbar or when clicked, aut ...

Can variables be transmitted through Real-Time Communication in JavaScript?

Currently, I am in the process of developing a multiplayer game using three.js. The basic framework is all set up and my next step is to implement the multiplayer aspect. After some research, I came across RTC as a solution that doesn't require comple ...

Troubleshooting JSONP Implementation with JQuery: Scope versus Async Problems

I've been trying to call a JSONP service using the $.ajax function: $.ajax({ url: jsonpURI, dataType: "jsonp", jsonpCallback: callback, success: function () { console.log("Success"); }, error: function (err) { ...

Is there a way to declare the different types of var id along with its properties in Typescript?

I recently received a task to convert a JavaScript file to a TypeScript file. One issue I am currently facing is whether or not I should define types for the 'id' with this expression, e.g., id={id}. So far, I have tried: Even though I defined ...

Calling Ajax inside each iteration loop

I have encountered numerous posts discussing this topic, but the solutions I came across do not quite suit my needs. Some experts suggest changing the code structure, however, I am unsure of how to go about doing that. What I desire: 1) Retrieve a list ...