Tengo el siguiente componente con un estado que realiza un seguimiento de las casillas de verificación:
import { useState } from "react"; function SideBar() { const [queryObject, setQueryObject] = useState({ genders: [], availabilities: [] }); function handleChange(event) { const { name, checked } = event.target; if (name === "male" || name === "female") { if (checked) { setQueryObject((prevQueryObject) => { prevQueryObject.genders.push(name); return prevQueryObject; }); } else { setQueryObject((prevQueryObject) => { return prevQueryObject.genders.filter((e) => e !== name); }); } return; } if (name === "available" || name === "not available") { if (checked) { setQueryObject((prevQueryObject) => { prevQueryObject.availabilities.push(name); return prevQueryObject; }); } else { setQueryObject((prevQueryObject) => { return prevQueryObject.availabilities.filter((e) => e !== name); }); } return; } } return ( <div> <input type="checkbox" checked={queryObject.genders.includes("male")} onChange={handleChange} name="male" /> <span>Male</span> <input type="checkbox" checked={queryObject.genders.includes("female")} onChange={handleChange} name="female" /> <span>Female</span> <br /> <input type="checkbox" checked={queryObject.availabilities.includes("available")} onChange={handleChange} name="available" /> <span>Available</span> <input type="checkbox" checked={queryObject.availabilities.includes("not available")} onChange={handleChange} name="not available" /> <span>Not available</span> </div> ); } export default SideBar;Cuando traté de hacer clic en las casillas de verificación, no se actualiza de inmediato, descubrí que cada vez que guardo mi archivo de texto nuevamente, el navegador se vuelve a cargar y luego se actualiza, creo que el problema está en mi función handleChange, es la forma en que estoy manejando el setQueryObject incorrecto?
El problema está en el enfoque de actualizar queryObject state. Dado que queryObject state es un objeto y si tratamos de modificar directamente el objeto de esta manera: -
setQueryObject((prevQueryObject) => { prevQueryObject.genders.push(name); return prevQueryObject; }); React no reconoce ningún cambio en el estado ya que el objeto tiene la misma referencia, por lo que no actualiza DOM . Por lo tanto, necesitamos crear una deep copy de ese objeto y volver a establecerlo en el object state para que se reconozca el cambio en el estado del objeto y React actualice el DOM.
setQueryObject((prevQueryObject) => { return{...prevQueryObject,genders:[...prevQueryObject.genders,name]}; });Código de trabajo completo aquí - CodeSandbox Link
Gracias a Yury volví a escribir el código y funciona.
import { useState } from "react"; function SideBar() { const [queryObject, setQueryObject] = useState({ genders: [], availabilities: [] }); function handleChange(event) { const { name, checked } = event.target; if (name === "male" || name === "female") { if (checked) { setQueryObject((prevQueryObject) => { return { ...prevQueryObject, genders: prevQueryObject.genders.concat(name) }; }); } else { setQueryObject((prevQueryObject) => { return { ...prevQueryObject, genders: prevQueryObject.genders.filter((e) => e !== name) } }); } return; } if (name === "available" || name === "not available") { if (checked) { setQueryObject((prevQueryObject) => { return { ...prevQueryObject, availabilities: prevQueryObject.availabilities.concat(name) }; }); } else { setQueryObject((prevQueryObject) => { return { ...prevQueryObject, availabilities: prevQueryObject.availabilities.filter( (e) => e !== name ) }; }); } return; } } return ( <div> <input type="checkbox" checked={queryObject.genders.includes("male")} onChange={handleChange} name="male" /> <span>Male</span> <input type="checkbox" checked={queryObject.genders.includes("female")} onChange={handleChange} name="female" /> <span>Female</span> <br /> <input type="checkbox" checked={queryObject.availabilities.includes("available")} onChange={handleChange} name="available" /> <span>Available</span> <input type="checkbox" checked={queryObject.availabilities.includes("not available")} onChange={handleChange} name="not available" /> <span>Not available</span> </div> ); } export default SideBar;