I have a table in my react-app and I stored some data in there. Now I have a function that everytime I click/select a table row, I load more details about that typical data somewhere else. The problem is that the user will want to know which row is currently selected so they wouldn't be confused whether the right one is clicked or not.
The table goes like this:
`<table>
<thead>
<tr>
<th>Name</th>
<th>LastName</th>
</tr>
</thead>
<tbody>
{myRecors.map((current) => (
<tr>
<td>{current.Name}</td>
<td>{current.LastName}</td>
</tr>
))}
</tbody>
</table>`
What I have tried:
const [isActive, setIsActive] = useState(false); // for setting a value whether it's clicked or not
const handleColorChange = (e) => {
setIsActive(current => !current);
console.log("e=",e);
};
`<table>
<thead>
<tr>
<th>Name</th>
<th>LastName</th>
</tr>
</thead>
<tbody>
{myRecors.map((current) => (
<tr style= {{
backgroundColor: isActive ? 'crimson' : '',
}}
onClick={handleColorChange(e)}
>
<td>{current.Name}</td>
<td>{current.LastName}</td>
</tr>
))}
</tbody>
</table>`
This will select all the table row, not only the one that is selected.
If I do the same thing to a <td>
then again, it will set backgroundColor to every row, not just one. What am I missing here?
CodePudding user response:
You cannot use one state and achieve this, since when you click on a table row, it will change the whole state and previously selected items will be changed as well. So inorder to keep the active state separately you will have to use a key inside the each item to keep the active state. I have done a simple implementation for this. Let me know if you have any questions.
// Get a hook function
const {useState} = React;
const dummyData = [
{
id: 1,
Name: 'Name 1',
LastName: 'Last Name 1'
},
{
id: 2,
Name: 'Name 2',
LastName: 'Last Name 2'
}
]
const Example = () => {
const formatData = (items) => {
return items.map((item) => ({...item, isActive: false}))
}
const [myRecords, setMyRecords] = useState(formatData(dummyData))
const handleColorChange = (id) => {
setMyRecords((prevState) => {
return prevState.map((item) => {
if(item.id === id) {
return {...item, isActive: !item.isActive}
}else {
return item;
}
})
})
}
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>LastName</th>
</tr>
</thead>
<tbody>
{myRecords.map((current) => (
<tr
key={current.id}
onClick={() => handleColorChange(current.id)}
style={{
backgroundColor: current.isActive ? 'crimson' : '',
}}
>
<td>{current.Name}</td>
<td>{current.LastName}</td>
</tr>
))}
</tbody>
</table>
);
};
// Render it
ReactDOM.createRoot(
document.getElementById("root")
).render(
<Example />
);
table, th, td {
border: 1px solid black;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
CodePudding user response:
Try this solution, I think we can go with index because this will be unique.
const [activeIndex, setIsActiveIndex] = useState('');
const handleColorChange = (index) => {
setIsActiveIndex(index);
};
{myRecors.map((current, index) => (
<tr style= {{
backgroundColor: index === activeIndex ? 'crimson' : '',
}}
onClick={ () => { handleColorChange(index); } }
key={`row-index-${index}`}>
<td>{current.Name}</td>
<td>{current.LastName}</td>
</tr>
))}