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

Using JavaScript to Show Variables When Clicked

I have been working on populating multiple divs with data stored in variables that change when an image is clicked. Here's a snippet of the code within my tag:</p> <pre><code>function displayName(name){ document.getElementById( ...

After stopping the interval with clearInterval(), you can then use the res.send method

I need to continuously log the current date and time to the server console then stop logging after a specified time, returning the final date and time to the user. How do I properly utilize ClearInterval() in this scenario? const express = require(" ...

Unable to process JSON data object

Having trouble with processing a json object. The form on the page contains a dropdown where selecting a truck number should autofill the rest of the form with data from a json file. Sample data: [ { "truckNum":"62-559", "description":"MOF ...

useSWR offers unlimited API requests

I have an API that only accepts POST requests and requires sending an ID to fetch the data, in this case an event. The issue I'm facing is that my SWR (stale-while-revalidate) hook is causing infinite calls. Here is the component code: const EventDe ...

Saving Data in an Angular Material Table: A How-to Guide

I have a basic angular material table and I am looking for a way to save the data displayed in each row when a button is clicked. Is it possible to save each row of data as an object and push it to an array? If so, how can I achieve this? <div class=& ...

Steps for building a dynamic component in React

I am looking to build a dynamic React component where the name is determined by data from the backend. For example: [ { "data": { "header": "this is header one", "article": "this is article one ...

Retrieving dates from a database and populating them into a jQuery UI Picker using PHP

I need to retrieve dates from the database using PHP and highlight them in a datepicker. Here is how I am attempting to accomplish this: HTML Date: <input type="text" id="datepicker"> // Static dates // An array of dates var eve ...

The issue of the marker vanishing upon refreshing the page on AngularJS

Currently, I am encountering a rather peculiar issue. Upon the initial page load, the code snippet below correctly displays a marker at the specified coordinates and ensures the map is properly centered: <div class="paddingtop"> <map data-ng- ...

The MAC slideshow circles at the bottom have been mysteriously chopped off

Utilizing the popular JQuery plugin Cycle for a slideshow on this site: bybyweb.com/pbm An issue has arisen - everything functions as expected on windows (across all major browsers), BUT on MAC (running lion 10.7.5, tested on one machine so far; unsure of ...

How can we rearrange the positions of three items in an array?

I am dealing with a function that returns an array of objects structured like this const allGreen = _.filter( sidebarLinks, side => !isServicePage(side.slug.current) ); https://i.stack.imgur.com/dR8FL.png I am attempting to rearrange the positions of ...

Unlocking the power of setting dynamic meta content

When using EJS for templating in my node.js webserver, everything has been running smoothly except for one issue. After integrating the head file into a page, I encountered the following error: SyntaxError: Unexpected identifier in /home/runner/superstrap/ ...

The Formik and React error is indicating that the '{ refetch: any; }' type is absent

When attempting to pass a prop down to my EmailSignupScreen, I encountered an error message. This issue arose while experimenting with Formik and Typescript. "message": "Type '{ refetch: any; }' is missing the following properties from type &apo ...

Custom pagination for next/previous links in Django REST framework

When it comes to backend operations, I have integrated the PageNumberPagination as the DEFAULT_PAGINATION_CLASS. Since I am utilizing vue.js along with fetch, there is no need for me to include the entire URL structure provided by django-rest-framework: " ...

Chat box custom scrollbar always positioned at the bottom

I have a personalized chat box where I included overflow-y for scrolling functionality. However, every time I input a message in the text box, it displays at the top of the scrollbar window. Is there a way to automatically show the most recent message I ...

InvalidAction: The function forEach cannot be applied to "res"

Here is the HTML code that I am currently working with: <div *ngIf="chart" class="col-xl-4 col-lg-6"> <div class="card cardColor mb-3"> <div class="card-header headColor"> <img class="img-fluid" src="../../../ ...

Having trouble with running 'npm init -y' in Windows? Here's a workaround for the VS

An error occurred when trying to initialize npm with the command "npm init -y". The name "WEB DEV" was deemed invalid. For a detailed log of this issue, please refer to: C:\Users\User\AppData\Roaming\npm-cache_logs\2020-12-05 ...

What steps should I take to set up my React project in order to eliminate .html extensions from the html files within the public

Currently, I am tackling a project that involves integrating a React app with a static website. Simply converting the HTML to JSX is not feasible because the website utilizes custom CSS that React cannot easily render without significant refactoring. I ha ...

Youtube video embedding showing cut edges on smaller screens

Looking for assistance with a Next.js and tailwind site I am building. Having trouble getting the video component to display properly on mobile screens. Tried various fixes but the video still gets cut off on smaller screen sizes. If anyone has a soluti ...

Shallow Rendering with Enzyme and Material-UI: The function you are providing does not include a theme within the context

I am completely new to writing tests and I am currently in the process of incorporating them into an existing React project. One of the components that I'm working on is a button component that requires a theme context to function properly. Despite my ...

Refresh the page once the function has been executed

Recently, I came across a basic javascript code that I need some help with. I want to reload the page after certain elements have faded out and back in. The problem is, I'm not sure where exactly I should include the window.location.reload(); function ...