How to update individually buttons icons got from a same component in React
-
I have a View All page. The page has a table with user data with actions that can be performed. The button has two different icons. Spinner icon and a default icon. I want to change the icon of the button until the task executes.
Ex: Showing spinner icon until M_1's disabling/deleting process works and showing back the lock/trash icon.
I know how to update one button icon by putting useState. When 1 row has 2 buttons that mean 2 useStates. So 2 rows mean 4 useStates. But that's not practical noh. I want to know how to do it the correct way.
Table with buttons:
View All Page:
import React, { useEffect, useState } from 'react' import { CButton, CCard, CCardBody, CCardHeader, CCol, CRow, CSpinner, CTable, CTableBody, CTableDataCell, CTableHead, CTableHeaderCell, CTableRow, } from '@coreui/react' import CIcon from '@coreui/icons-react' import { cilTrash, cilLockLocked } from '@coreui/icons' const ViewAll = () => { const [usersData, setUsersData] = useState({}) const [disabled, setDisabled] = useState(false) const handleLoadMembers = async () => { try { const _data = await fetch('http://localhost:4000/api/v1/member/list', { method: 'GET', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + localStorage.getItem('token'), }, }) if (_data.status !== 200) { throw new Error() } const data = await _data.json() setUsersData(data.members) } catch (err) { console.error(err) } } const handleDelete = async (id) => { alert('clicked') try { const _data = await fetch('http://localhost:4000/api/v1/member/remove/' + id, { method: 'GET', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + localStorage.getItem('token'), }, }) window.location.reload() console.log(_data) } catch (err) { console.error(err) } } useEffect(() => { handleLoadMembers() }, []) return ( <CRow> <CCol xs={12}> <CCard className="mb-4"> <CCardHeader> <strong>All Members</strong> </CCardHeader> {usersData.length > 0 ? ( <CCardBody> <p className="text-medium-emphasis small">Here the all members of your community.</p> <CTable hover bordered> <CTableHead color="dark"> <CTableRow> <CTableHeaderCell scope="col">Member ID</CTableHeaderCell> <CTableHeaderCell scope="col">Name</CTableHeaderCell> <CTableHeaderCell scope="col">Email</CTableHeaderCell> <CTableHeaderCell scope="col">Actions</CTableHeaderCell> </CTableRow> </CTableHead> <CTableBody> {usersData.map((item, index) => { return ( <CTableRow key={index}> <CTableHeaderCell scope="row">M_{item.index}</CTableHeaderCell> <CTableDataCell>{item.name}</CTableDataCell> <CTableDataCell>{item.email}</CTableDataCell> <CTableDataCell class="d-flex justify-content-evenly"> <CButton color="danger" size="sm" disabled={disabled} onClick={() => handleDelete(item._id)} > {disabled ? ( <CSpinner component="span" className="me-2" size="sm" aria-hidden="true" /> ) : ( <CIcon icon={cilTrash} className="me-2" /> )} Delete </CButton> <CButton color="warning" size="sm" disabled={disabled} onClick={() => handleDelete(item._id)} > {disabled ? ( <CSpinner component="span" className="me-2" size="sm" aria-hidden="true" /> ) : ( <CIcon icon={cilLockLocked} className="me-2" /> )} Disable </CButton> </CTableDataCell> </CTableRow> ) })} </CTableBody> </CTable> </CCardBody> ) : ( 'No data' )} </CCard> </CCol> </CRow> ) } export default ViewAll