1

I'm trying to add a class to ONE specific element. The user clicks a remove button, then the entire row containing the button in a table should appear disabled after a class "removed" is added to the containing row div. There are multiple rows created using array.map. I tried this: How to access/override the className of an element using refs? But useRef targets only the last version of the div created in the iteration, useState for conditional className changes all iterations of that div.

const AccordionBody = ({...props }) => {
  
  const [data, setData] = useState(null);
  //data is loaded from api
  // set state 
  ...
  const handleRemove = (id) => {
    // ... sending remove ID to api 
    // add class "removed" to grandparent of button
  };

  return (
   {data.list.map((item) => (
          // change this parent div. Tried useRef and conditional className here.
          <div className={`c-table__row`} key={item.id} >
            <div className="c-table__row__item">
              // this is the button triggering the change
              <div className="e-btn__x" onClick={(e) => handleRemove(item.id)}></div>
              <img className="u-img--round" src={item.icon}/>
              <span className="c-table__cell">
                {item.name}
              </span>
            </div>
            <div className="c-table__row__item ">
                {item.location}
            </div>
            //more info in this row
            ...
          </div>
        ))}
}
  • How about adding a specific (boolean) property on that item in the state? And what should happen if API call fails for some reason? – raina77ow Sep 20 '20 at 05:56

1 Answers1

1

Put the status of whether a row is disabled or not into the data.list array in state. Probably something like:

{data.list.map((item, i) => (
  // ...
  onClick={(e) => handleRemove(i)
const handleRemove = (index) => {
  setData({
    ...data,
    list: [
      ...data.list.slice(0, index),
      { ...data.list[index], disabled: true },
      ...data.list.slice(index + 1),
    ]
  });
};

Then, when rendering, use the disabled property to give the row a class name.

<div
    className={`c-table__row${item.disabled ? ' disabled' : ''}`}
    key={item.id}
>
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thanks certainperformance and @raina77ow, that way works. I guess I was thinking there must be some advanced way to implement useRef that I didn't know. – Lisa Ziegler Sep 20 '20 at 06:36
  • There is, but putting the status into state is the more react-way of doing things. – CertainPerformance Sep 20 '20 at 06:37
  • Makes sense, and seems obvious now. Honestly modifying data in state didn't that way didn't even occur to me, and I forgot about the index param in array.map. – Lisa Ziegler Sep 20 '20 at 06:47