He probado casi todas las soluciones similares a mi problema, pero ninguna funciona. Tengo un estado simple y cambio el valor de este estado en una función como la siguiente, handleOnClick está llamando al evento onClick de un botón. También estoy usando el enrutador (si cambia algo);
import { useState} from "react" import { BrowserRouter as Router, Route, Link, useHistory} from "react-router-dom"; const Buton = () => { let x = ""; const [lowerState, setLower] = useState("") const history = useHistory(); const handleOnClick = () => { x = document.getElementById("my_input").value.toLowerCase(); setLower(x) console.log(x) //this prints the current value console.log(lowerState) //this DOES NOT prints the current value, but // when I put another text into the input and click // to button, it prints the first value I put here history.push('/test', {params : lowerState}) }; . . . return (...) } export default Buton Ahora x es un valor que regresa de un elemento HTML de input . Cuando configuro este valor como un estado y un registro de la consola, no imprime el valor primero, cuando ingreso algo nuevamente, luego imprime el primer valor. Así que es como si viniera 1 paso atrás.
He usado useEffect() , puse un segundo parámetro para setLower como console.log(lowerState) y otras cosas en Internet que la gente sugirió, pero ninguna funciona. Cada vez, el estado viene 1 paso atrás. ¿Cómo puedo hacer que este estado cambie inmediatamente?
Si desea utilizar el valor de una entrada en una función de evento de usuario, la mejor manera (y la menos problemática) es vincular su valor de entrada al estado local y luego simplemente hacer referencia a ese estado en su función de devolución de llamada.
Intente evitar extraer imperativamente valores del DOM usando getElementById , etc. Esto es lo que quiero decir:
const [value, setValue] = useState(''); // This will keep everything updated until you need to use it handleChange(event) { setValue(event.target.value); } // Then just grab whatever is in local state handleClick() { history.push('/test', {params : value}); } return ( <input value={value} onChange={handleChange} /> // Your button is here too )Esto se debe a que cuando llama a setLower(x) no es una llamada asíncrona. Así que no espera. Es por eso que obtiene el 1 paso antes del valor en su estado justo después de establecer el valor.
Documento oficial: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
Cuando llamas a setLower(x) , no actualiza inmediatamente lowerState . El nuevo valor estará disponible la próxima vez que se represente. Debido a eso console.log(x) "funciona" (ya que usa el nuevo valor que obtiene como parámetro), pero console.log(lowerState) usa el valor anterior que aún no se ha actualizado al estado en ese momento .
Si desea que history.push('/test', {params : lowerState}) funcione, debe usar la x allí en lugar de lowerState . O llámelo dentro de un useEffect con lowerState y tenga lowerState como un parámetro de dependencia para el gancho.