0
votes

I'm trying to remove a CSS class from a specific item when clicking on that item's button. Removing the CSS class will make a menu appear. How would I go about doing this with React? Here's the code.

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

  }

<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"> // I want to remove "invisible"
                        Delete
                      </button>
                      <br></br>
                    </div>
                    <p className="body-text">{item.body}</p>
                  </div>
                )
              })}
          </div>

As far as I'm concerned using state as the className would remove or alter the CSS of each item in the "sortedData" array and make the menus for all items appear. I only want the menu for one of the items to appear.

1
This is a good moment to break the elements out into their own component, which will forego needing to store item data as data-attributes, but instead as state within each item (or lifted to the parent if need be). - pilchard
What class? On what element? (e.target.parentElement.children[1] will either be the edit button or undefined, depending on where within the button the user clicks.) And are you using class components or hooks? - T.J. Crowder

1 Answers

0
votes

As pilchard said, you probably want to make each of those its own component with its own "showing" state, or at least "showing" prop.

As far as I'm concerned using state as the className would remove or alter the CSS of each item in the "sortedData" array and make the menus for all items appear. I only want the menu for one of the items to appear.

That would be true if you used a single flag in state. But instead, use a set of flags, one flag for each menu, perhaps keyed by item._id.

Assuming you don't do the refactoring pilchard (and I) suggest:

You haven't shown us enough code for me to know whether you're using class components or function components, so I'm going to guess function components with hooks. If so, the initial state would be:

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

Then when rendering, you'd assign the class:

<theElement className={showing.has(item._id) ? "class-if-any-to-show-it" : "class-if-any-to-not-show-it" ...

To toggle, in the button pass the ID:

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

and then update state as appropriate:

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