2

I'm new working with react hooks so I wanted a hand in a problem that is appearing me when I try to change the value of a variable. When I'm trying to set a value returned from an external API, it prints that in the data returns information that can be captured, however, using useState (setVariable) to use that value in other part, it appears in blank. Here is an example of my code:

const InicioSesion: React.FC<{}> = () => {

const [token, setToken] = useState('');
const [success, setSucess] = useState(false);
const [userLogin, setUserLogin] = useState({
    'nombre' : '',
    'password' : ''
});

const actualizarUser = (e: any)  => {
    setUserLogin({
        ...userLogin,
        [e.target.name]: e.target.value
    });
}

const sendInfo = () => {
    axios.post('https://service.herokuapp.com/login',  JSON.parse('{"nombre":"' + userLogin.nombre + '", "password":"' + userLogin.password + '"}') )
    .then(res => {
        console.log(res);
        console.log(res.data.Authorization); //Here appears like I got the token as response

        setToken(res.data.Authorization); // Here I'm trying to set my variable with the value obtained.

        console.log(token); //Here prints as if I didn't asing any value.

        handleOpen();
    }).catch(error => {
        console.log(error.response)
    });
}

const handleOpen = () => {
    setSucess(true);
}

const handleClose = () => {
    setSucess(false);
}

return(
    <div>
        <h1>Iniciar sesión</h1>
        <Container placeholder>
            <Segment>
            <Form>
                <Form.Field>
                    <label>Correo</label>
                    <input placeholder='Ingresa tu correo' name='nombre' onChange={actualizarUser}/>
                </Form.Field>
                <Form.Field>
                    <label>Contraseña</label>
                    <input placeholder='Ingresa tu contraseña' name='password' onChange={actualizarUser}/>
                </Form.Field>

                <Link to={{ pathname:'/init/home', state:{ value: token } }}>
                    <Button type='submit'>SubmitNuevo</Button>
                </Link>
                <Button type='submit' onClick={sendInfo}>Prueba</Button>
            </Form>
            </Segment>
        </Container>

        <Modal show={success} onHide={handleClose}>
            <Modal.Header closeButton>
            <Modal.Title>Registro exitoso</Modal.Title>
            </Modal.Header>
            <Modal.Body>
                Su local se ha creado exitosamente. Ahora puede iniciar sesión.
            </Modal.Body>
            <Modal.Footer>
                <Button variant="secondary" onClick={handleClose}>
                    Cerrar
                </Button>
            </Modal.Footer>
        </Modal>
    </div>
);

Thank you for you help.

adiga
  • 34,372
  • 9
  • 61
  • 83
  • Setting state is asynchronous in React so it won't show it updated if you `console.log` it on the next line. If you want more info or examples just search SO, there's like a million posts around this already – Jayce444 May 15 '20 at 04:20

3 Answers3

2

The reason you do not see the updated state is because updating of state is asynchoronous, and you will need to wait for the next re-render before the updated state values will be shown correctly. Therefore, doing the below will still result it the previous token value to be logged:

setToken(res.data.Authorization); 
console.log(token); 

If you wish to print/log the value of the updated token, one solution would be to use the useEffect hook:

useEffect(() => {
  console.log(token);
}, [token]);

This will print the value of the new token from the API response when the request is returned and the state has been updated.

wentjun
  • 40,384
  • 10
  • 95
  • 107
0

This is because setToken method is asynchronous and the console.log(token); is executed before the setToken(res.data.Authorization);. You can use useEffect hook with token argument to detect when the token is changed and execute the code in useEffect.

PR7
  • 1,524
  • 1
  • 13
  • 24
0

useState works async, therefore there is a lag to the state updating. I suggest using the useRef Hook to update immediately. here is some documentation: https://reactjs.org/docs/hooks-reference.html#useref

Tomas Gonzalez
  • 188
  • 2
  • 8