es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

reactjs: una función componente de contexto no actualiza su variable; ¿usestate no funciona de inmediato?

Estoy trabajando en la autenticación de mi aplicación, así que he creado un contexto para gestionarla:

import React, { useState } from "react";

const AuthContext = React.createContext({
    token: "",
    isLoggedIn: false,
    login: (token) => { },
    logout: () => { },
});

export const AuthContextProvider = (props) => {
    const [token, setToken] = useState(null);
    const [userIsLoggedIn, setUserLoggedIn] = useState(false);

    const loginHandler = async (token) => {
        setToken(token);
        setUserLoggedIn(true);
        console.log(userIsLoggedIn)   //imprime false
    };

    const logoutHandler = () => {
        setToken(null);
        setUserLoggedIn(false);
    };

    const contextValue = {
        token: token,
        isLoggedIn: userIsLoggedIn,
        login: loginHandler,
        logout: logoutHandler,
    };

    return (
        <authcontext.provider value="{contextValue}">
            {props.children}
        </authcontext.provider>
    );
};

export default AuthContext;

El problema es que cuando llamo a context.login('some token') desde un componente externo y luego hago console.log(context.isLoggedIn), obtengo false la primera vez, pero si vuelvo a llamar context.login('some token') obtengo true. Cada vez sucesiva después de eso obtengo true ahora. Podría tener que ver con el hecho de que el “console.log(userIsLoggedIn)” dentro de loginHandler muestra “false” (la primera vez que se llama a context.login) a pesar de que setUserLoggedIn está justo encima de él. Creo que la variable userIsLoggedIn se cambia después de que el contexto se actualiza en el componente en el que se utiliza, pero no sé cómo solucionarlo. Agradeceré cualquier ayuda con esto.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    La razón por la que obtienes “false” la primera vez que llamas a context.login(‘some token’) y “true” después es porque las actualizaciones de estado son asíncronas en React. Esto significa que cuando llamas a setUserLoggedIn(true), la variable de estado userIsLoggedIn no se actualiza inmediatamente, sino en el siguiente re-renderizado del componente. Por lo tanto, cuando llamas a console.log(userIsLoggedIn) justo después de establecer el estado, aún estás registrando el valor antiguo de userIsLoggedIn.

    Para solucionar esto, puedes utilizar la función de devolución de llamada (callback) de useState para realizar console.log después de que se haya actualizado el estado. Aquí tienes una versión actualizada de tu código que debería funcionar:

    import React, { useState } from "react";
    
    const AuthContext = React.createContext({
        token: "",
        isLoggedIn: false,
        login: (token) => { },
        logout: () => { },
    });
    
    export const AuthContextProvider = (props) => {
        const [token, setToken] = useState(null);
        const [userIsLoggedIn, setUserLoggedIn] = useState(false)
    
        const loginHandler = async (token) => {
            setToken(token);
            setUserLoggedIn(true, () => {
                console.log(userIsLoggedIn); // debería registrar "true" aquí
            });
        };
    
        const logoutHandler = () => {
            setToken(null);
            setUserLoggedIn(false);
        };
    
        const contextValue = {
            token: token,
            isLoggedIn: userIsLoggedIn,
            login: loginHandler,
            logout: logoutHandler,
        };
    
    
        return (
            <authcontext.provider value="{contextValue}">
                {props.children}
            </authcontext.provider>
        );
    };
    
    export default AuthContext;
    

    Ten en cuenta el uso del segundo argumento en setUserLoggedIn, que es la función de devolución de llamada que se ejecuta después de que se actualice el estado. Esto debería registrar el valor correcto de isLoggedIn en la consola.

Comments are closed.