Aquí está el problema: estoy tratando de llamar a 2 funciones con un clic de botón. Ambas funciones actualizan el estado (estoy usando el enlace useState). La primera función actualiza el valor1 correctamente a 'nuevo 1', pero después de 1s (setTimeout) se dispara la segunda función, y cambia el valor 2 a 'nuevo 2' ¡PERO! Establece el valor1 de nuevo a '1'. ¿Por qué está pasando esto? ¡Gracias por adelantado!
import React, { useState } from "react";
const Test = () => {
const [state, setState] = useState({
value1: "1",
value2: "2"
});
const changeValue1 = () => {
setState({ ...state, value1: "new 1" });
};
const changeValue2 = () => {
setState({ ...state, value2: "new 2" });
};
return (
<>
<button
onClick={() => {
changeValue1();
setTimeout(changeValue2, 1000);
}}
>
CHANGE BOTH
</button>
<h1>{state.value1}</h1>
<h1>{state.value2}</h1>
</>
);
};
export default Test;
javascript
reactjs
react-hooks
Bartek
fuente
fuente

changeValue2?useStateusar o en su lugaruseReducer.const [state, ...], y luego haciendo referencia a él en el setter ... Utilizará el mismo estado todo el tiempo.useStatellamadas separadas , una para cada "variable".Respuestas:
Bienvenido al infierno de cierre . Este problema ocurre porque cada vez que
setStatese llama,stateobtiene una nueva referencia de memoria, pero las funcioneschangeValue1ychangeValue2, debido al cierre, mantienen lastatereferencia inicial anterior .Una solución para garantizar la
setStatedechangeValue1ychangeValue2recupera el estado más reciente es el uso de una devolución de llamada (que tiene el estado anterior como un parámetro):Puede encontrar una discusión más amplia sobre este tema de cierre aquí y aquí .
fuente
Sus funciones deberían ser así:
Por lo tanto, se asegura de no perder ninguna propiedad existente en el estado actual utilizando el estado anterior cuando se activa la acción. También así evitas tener que gestionar cierres.
fuente
Cuando
changeValue2se invoca, el estado inicial se mantiene para que el estado vuelva al estado inicial y luegovalue2se escribe la propiedad.La próxima vez que
changeValue2se invoca después de eso, mantiene el estado{value1: "1", value2: "new 2"}, por lo quevalue1se sobrescribe la propiedad.Necesita una función de flecha para el
setStateparámetro.fuente
Lo que pasa es que tanto
changeValue1ychangeValue2ver el estado del render que fueron creados en , por lo que cuando su componente rinde por primera vez estas 2 funciones, véase:Cuando hace clic en el botón,
changeValue1se llama primero y cambia el estado a{value1: "new1", value2: "2"}lo esperado.Ahora, después de 1 segundo,
changeValue2se llama, pero esta función aún ve el estado inicial ({value1; "1", value2: "2"}), por lo que cuando esta función actualiza el estado de esta manera:setState({ ...state, value2: "new 2" });terminas viendo:
{value1; "1", value2: "new2"}.fuente
fuente