Estoy tratando de crear una serie de permisos de usuario, que pueden controlarse mediante un conjunto de casillas de verificación. cuando marco una casilla y console.log() la matriz se ve bien con todas las premisiones que verifiqué, pero cuando desmarco la casilla, console.log() devuelve el valor anterior de la matriz y se actualizará solo en el siguiente clic
const [prems, setPrems] = useState([]); const handleCheckbox = (e) => { let arr = prems if (e.target.checked) { arr.push(e.target.value) setPrems(arr) console.log(prems) //shwos the array with all the checked values } else { let newArr = arr.filter((item) => { return item !== e.target.value }) setPrems(newArr) console.log(prems) //shows the array still with the value i unchecked } };el evento en las casillas de verificación es onChange y funciona igual con onClick
Puede actualizar el estado de manera confiable usando actualizaciones funcionales en useState :
const [prems, setPrems] = useState({}); const handleCheckbox = (e) => { setPrems((prevState) => { return { ...prevState, [e.target.value]: e.target.checked }; }); }; Como señaló @ Kamlesh Sharma, el estado es asíncrono, por lo que es posible que el registro no muestre el estado actual. En su lugar, podría representar los prems de la siguiente manera para ver el estado actual:
<ul> {Object.keys(prems).map((prem) => { if (prems[prem]) { return <li key={prem}>{prem}</li>; } })} </ul>Puede ver el código en acción con casillas de verificación en este JSFiddle .
EDITAR:
Si es particularmente importante que prems sea una matriz en lugar de un objeto, la llamada setPrems se puede modificar de la siguiente manera:
setPrems((prevState) => { if (e.target.checked) { return [...prevState, e.target.value]; } else { return prevState.filter((elem) => elem !== e.target.value); } });El estado de reacción se establece de forma asíncrona . Por lo tanto, no puede confiar en el estado justo después de actualizarlo.
Para buscar los cambios de ese estado, es mejor ponerlo dentro de un gancho useEffect y establecer el nombre de la variable como dependencia:
React.useEffect(() => { // the prems have changed }, [prems]);También tienes un gran error en tu código:
let arr = prems if (e.target.checked) { arr.push(e.target.value) ... Aquí, está asignando la variable prems a arr y mutando la variable arr . ¡HACEN REFERENCIA AL MISMO OBJETO! Entonces, empujar todo a arr también lo empujará a prems y viceversa. Nunca hagas eso. Lea más sobre los objetos JS aquí .
ACTUALIZACIÓN: Este es el código correcto:
const handleCheckbox = (e) => { if (e.target.checked) { setPrems([ ...prems, e.target.value ]) } else { const newPrems = prems.filter((item) => item !== e.target.value); setPrems(newPrems) } }; React.useEffect(() => { // do something }, [prems]);