Reputation: 49
I'm trying to build a reusable table from scratch without using extra npm packages.
The problem I've been trying to solve all day is selecting one row on checkbox click.
I wanted to achieve this by changing className to 'blue' on state change. className={selectValue ? "blue" : null}
What's happening right now is whichever row I select its selecting all of the rows.
I was hoping you could point me into the right direction. What are some other ways of changing background color when clicking checkbox?
I appreciate the help.
Code and Codesandbox below.
https://codesandbox.io/s/friendly-resonance-48iu3?file=/src/App.js
import React, { useState, useEffect } from "react";
import "../../App.css";
function Student() {
const [studentState, setStudentState] = useState([]);
const [selectValue, setSelectValue] = useState("");
useEffect(() => {
let studentState = [
{ id: 1, firstname: "Stone", lastname: "Cold", major: "wwf" },
{ id: 2, firstname: "Addrian", lastname: "Fox", major: "wwf" },
{ id: 3, firstname: "Harry", lastname: "Pit", major: "wwf" },
];
setStudentState(
studentState.map((d) => {
return {
select: false,
id: d.id,
firstname: d.firstname,
lastname: d.lastname,
major: d.major,
};
})
);
}, []);
return (
<div className="container">
<table className="table table-bordered">
<thead>
<tr>
<th scope="col">
<input
type="checkbox"
onChange={(e) => {
let checked = e.target.checked;
setStudentState(
studentState.map((d) => {
d.select = checked;
return d;
})
);
}}
></input>
</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
{studentState.map((d, i) => (
<tr key={d.id} className={selectValue ? "blue" : null}>
<th scope="row">
<input
onChange={(event) => {
let checked = event.target.checked;
setStudentState(
studentState.map((data) => {
if (d.id === data.id) {
data.select = checked;
}
return data;
})
);
setSelectValue(checked)
}}
type="checkbox"
checked={d.select}
id={d.id}
></input>
</th>
<td>{d.firstname}</td>
<td>{d.lastname}</td>
<td>{d.major}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
export default Student;
Upvotes: 0
Views: 69
Reputation: 194
you are using a single state to check the selected row which cant be done as a single state can not hold the value for all the rows. I see you also have a status select
inside each object which you use to check/uncheck the checkboxes. We can use the same to show colored rows as well. Here is an updated codesandbox you can have a look at. Let me know if any questions.
export default function App() {
const [studentState, setStudentState] = useState([]);
useEffect(() => {
let studentState = [
{ id: 1, firstname: "Stone", lastname: "cold", major: "wwf" },
{ id: 2, firstname: "Addrian", lastname: "Fox", major: "wwf" },
{ id: 3, firstname: "Harry", lastname: "Pit", major: "wwf" }
];
setStudentState(
studentState.map((d) => {
return {
select: false,
id: d.id,
firstname: d.firstname,
lastname: d.lastname,
major: d.major
};
})
);
}, []);
return (
<div className="container">
<table className="table table-bordered">
<thead>
<tr>
<th scope="col">
<input
type="checkbox"
onChange={(e) => {
let checked = e.target.checked;
setStudentState(
studentState.map((d) => {
d.select = checked;
return d;
})
);
}}
></input>
</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
{studentState.map((d, i) => (
<tr key={d.id} className={d.select ? "blue" : null}>
<th scope="row">
<input
onChange={(event) => {
let checked = event.target.checked;
setStudentState(
studentState.map((data) => {
if (d.id === data.id) {
data.select = checked;
}
return data;
})
);
}}
type="checkbox"
checked={d.select}
id={d.id}
></input>
</th>
<td>{d.firstname}</td>
<td>{d.lastname}</td>
<td>{d.major}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
Upvotes: 1