how to leave table rows opened on react table?

I put a button for SHOW & HIDE on description part since length of description will be pretty long. I want to leave these buttons working individually and also leave these buttons opened unless I click it again.

The problem is if I click first one and click second one, then it doesn’t open second one but close first one.

Here’s my code and I know I should work on isoPen, currentReport and key. I just have no idea how to work it out.

const [isOpen, setIsOpen] = useState(false);
const [currentReport, setCurrentReport] = useState(0);
<Table style={{ marginTop: "30px" }}>
    <thead>
        <tr>
            <th class="name">name</th>
            <th class="description">description</th>
            <th class="date">date</th>
        </tr>
    </thead>
    <tbody>
        {data&&
            data.map((value,key)=>
            (
                <tr key={key}>
                    <td class="name">{value.name}</td>
                    <td >
                        <Button color="primary" onClick={() => {
                            setIsOpen(!isOpen);
                            setCurrentReport(key);
                            console.log(currentReport);
                        }}>Show/Hide</Button>
                            <Collapse isOpen={isOpen&&(currentReport===key)}>
                                <Card>
                                    ...
                                </Card>
                                <div style={{marginTop:'5px', marginLeft:'2px', textAlign:'right'}}>
                                    <Button color='info' onClick={()=>{
                                        setEditOn(!editOn);
                                        setCurrentReport(key);
                                    }}>Update</Button>
                                        <Modal isOpen={editOn&&(currentReport===key)} toggle={toggle}>
                                            ...
                                        </Modal>
                                    <Button color='danger' onClick={()=>{
                                        ...
                                    }}>Delete</Button>
                                </div>
                            </Collapse>
                    </td>
                    <td class="date" style={{ fontSize:'smaller' }}>{value.year}/ <br/>{value.month}/ {value.date}</td>
                </tr>
            ))}
    </tbody>
</Table>

Also since I put 0 in useState() of const [currentReport, setCurrentReport] though I click second or third one at the first time, console.log(currentReport) shows 0 at the first time. Obviously… What value should I put in useState() of const [currentReport, setCurrentReport]?

Answer

Here’s my code and I know I should work on isoPen, currentReport and key. I just have no idea how to work it out.

Your intuition is correct. You have to change isOpen flag into a list of flags where index in this list would correspond with index in your data which is mapped to components. Just don’t forget to initialize it. currentReport will have nothing to do with show&hide mechanic. Each time you use isOpen you should now use isOpen[key] instead:

<Collapse isOpen={isOpen&&(currentReport===key)}>

intoto

<Collapse isOpen={isOpen[key] && (currentReport===key)}>

Also you need to change button’s behaviour: it needs to copy the isOpen array, change the value under the index and then set the state to the new value (you can’t just change the value in the array bacause react won’t see this modified array as a new value- the reference must change)

<Button color="primary" onClick={() => {
    let newIsOpen = [...isOpen];      //copy array
    newIsOpen[key] = !newIsOpen[key]; //toggle flag
    setIsOpen(newIsOpen);             //set new state
    setCurrentReport(key);
    console.log(currentReport);
 }}>Show/Hide</Button>

I’m uncertain about what currentReport is for, but I guess it points out which report is about to be modified somehow (if that’s the case I would recommend adding another button for it), so for the first time (before any report is pointed by user) you should simply put there null or even undefined value.

const [currentReport, setCurrentReport] = useState(undefined);