Estoy mapeando datos de una base de datos en una tabla html donde cada fila tiene un botón de alternar para marcar si están ausentes o no. Sin embargo, no estoy seguro de cómo guardar el estado del botón de alternar de cada fila, ya que todos serán diferentes.
function Component() { const [students, setStudents] = useState([]); const [absent, setAbsent] = useState(false); const updateAbsent = () => { console.log(absent); }; return ( <div className="attendance-today-container"> <h1>Daily attendance</h1> <table ref={table}> <tr> <th>First Name</th> <th>Last Name</th> <th>Absent?</th> </tr> {students.map((student, i) => { return ( <tr> <td key={i}>{student.firstName}</td> <td>{student.lastName}</td> <td> <label class="switch"> <input type="checkbox" onClick={() => { setAbsent(!absent); }} /> <span class="slider round"></span> </label> </td> </tr> ); })} </table> <button onClick={updateAbsent}>Send</button> </div> ); }Una forma fácil sería almacenar los datos de los estudiantes y si están presentes o ausentes en el mismo estado.
Cada estudiante podría tener una identificación para poder identificarlo fácilmente. Una función podría pasar por la matriz de estado del estudiante e identificar con la identificación qué estudiante se marcó como ausente o presente.
const data = [ { id: 1, firstName: 'John', lastName: 'Doe', absent: false }, { id: 2, firstName: 'Jane', lastName: 'Doe', absent: false }, ]; const StudentList = () => { const [students, setStudents] = useState(data); const updateAbsent = () => { const absents = students.filter((student) => student.absent === true); console.log(absents); }; const handleToggleAbsent = (toggleStudent) => { setStudents((prevStudents) => prevStudents.map((student) => { if (student.id !== toggleStudent.id) return student; return { ...student, absent: !student.absent }; }) ); }; return ( <div className="attendance-today-container"> <h1>Daily attendance</h1> <table> <thead> <tr> <th>First Name</th> <th>Last Name</th> <th>Absent?</th> </tr> </thead> <tbody> {students.map((student) => { return ( <StudentItem student={student} key={student.id} onToggleAbsent={handleToggleAbsent} /> ); })} </tbody> </table> <button onClick={updateAbsent}>Send</button> </div> ); }; const StudentItem = (props) => { const { student, onToggleAbsent } = props; return ( <tr> <td>{student.firstName}</td> <td>{student.lastName}</td> <td> <label className="switch"> <input type="checkbox" onClick={onToggleAbsent.bind(null, student)} /> <span className="slider round"></span> </label> </td> </tr> ); }; export default StudentList;El concepto está en la línea de lo que sugirió Sheik Yerbouti y lo que SamiElk ha demostrado.
Tome la matriz de objetos de estudiante y agregue una propiedad llamada absent a cada uno y configúrelo como false de forma predeterminada. Luego haga que las casillas de verificación correspondientes cambien el valor absent correctamente para cada estudiante según el índice del objeto en la matriz Y el valor actual de su propiedad absent . Creé una función llamada getData que simulará su llamada API para obtener los datos de los estudiantes. Aquí está el código:
import { useEffect, useState } from "react"; import "./styles.css"; const getData = () => { return new Promise(resolve => { resolve([{firstName: "John", lastName: "Marks"}, {firstName: "Garry", lastName: "Nelson"}]); }) } export default function App() { const [students, setStudents] = useState([]); const markAbsent = (i) => { setStudents(prev => prev.map((s, index) => ({...s, absent: i === index ? !s.absent : s.absent})) ) } useEffect(() => { getData() .then(data => { data = data.map(i => ({absent: false, ...i})); setStudents(data); }) }, []) return ( <div className="attendance-today-container"> <h1>Daily attendance</h1> <table> <tr> <th>First Name</th> <th>Last Name</th> <th>Absent?</th> </tr> {students.map((student, i) => { return ( <tr> <td key={i}>{student.firstName}</td> <td>{student.lastName}</td> <td> <label class="switch"> <input type="checkbox" defaultChecked={student.absent} onClick={() => markAbsent(i)} /> <span className="slider round"></span> </label> </td> </tr> ); })} </table> <button onClick={() => false}>Send</button> </div> ); } Tenga en cuenta que no estoy seguro de lo que se supone que debe hacer el botón Send , así que lo dejé sin funcionar. Aquí hay un enlace de Sandbox para que juegues.