Cuando salgo de la página de Home , el estado se actualiza y la página muestra una opción de inicio de sesión, pero después de volver a iniciar sesión, la página vuelve a mostrar una opción de inicio de sesión hasta que se actualiza, después de actualizar la página, ¿muestra el nombre de usuario? ¿Por qué el valor del contexto no se refleja inmediatamente?
Iniciar sesión.js:
const submit = () => { Axios.post("http://localhost:3001/login", data).then((res) => { localStorage.setItem("bankDetails", res.data[0].acc_no); navigate("/Home"); }); }; return ( <form onSubmit={submit}> <input ... /> ... </form> )Inicio.js:
import { useContext } from "react"; import { LoginContext, DetailsContext } from "../App"; function Account() { const isValid = useContext(LoginContext); const userDetails = useContext(DetailsContext); const load = () => { localStorage.removeItem("bankDetails"); window.location.reload(); } return isValid ? ( <div className="personal-info"> <h3>Welcome {userDetails.Username}</h3> <h3 onClick={load}>LogOut</h3> </div> ) : ( <h1>You Need to Login First !!!</h1> ); }Aplicación.js:
export const LoginContext = React.createContext(); export const DetailsContext = React.createContext(); function App() { const username = localStorage.getItem("bankDetails"); const [userDetails, setUserDetails] = useState(); const [isValid, setisValid] = useState(false); useEffect(() => { if (username !== null) { Axios.post("http://localhost:3001/userDetails", { username: username, }).then((res) => { if (res.data.err) { console.log("err"); } else { setUserDetails(res.data.details[0]); setisValid(true); } }); } }, [username]); return ( <LoginContext.Provider value={isValid}> <DetailsContext.Provider value={userDetails}> <Router> <Routes> <Route path="/Login" element={<Login />} /> <Route path="/Home" element={<Home />} /> </Routes> </Router> </DetailsContext.Provider> </LoginContext.Provider> ); }Eso es porque dentro de la función de submit no le pediste al contexto que actualizara nada. El componente de su App no está viendo cambios dentro de localStorage , lo único que está actualizando después de iniciar sesión. La App , como lo hizo, verifica el localStorage solo durante la carga. Es por eso que funciona cuando inicia sesión y luego actualiza la página.
Lo que puede hacer que no cambiaría tanto su estructura actual es cambiar el componente de la App de la siguiente manera (agregué comentarios donde cambié cosas):
export const LoginContext = React.createContext(); export const DetailsContext = React.createContext(); function App() { const [userDetails, setUserDetails] = useState(); const [isValid, setisValid] = useState(false); useEffect(() => { // I moved this line here in the callback const username = localStorage.getItem("bankDetails"); if (username !== null) { Axios.post("http://localhost:3001/userDetails", { username: username, }).then((res) => { if (res.data.err) { console.log("err"); } else { setUserDetails(res.data.details[0]); } }); } }, [isValid]); // I changed the dependencies array return ( // I'am passing down setisValid as part of LoginContext <LoginContext.Provider value={{ isValid, setisValid }}> <DetailsContext.Provider value={userDetails}> <Router> <Routes> <Route path="/Login" element={<Login />} /> <Route path="/Home" element={<Home />} /> </Routes> </Router> </DetailsContext.Provider> </LoginContext.Provider> ); } Luego tome isValid y setisValid dentro del componente de inicio de Login . Cambie su función de submit y agregue un useEffect que haría la redirección. Al igual que:
const {isValid, setisValid} = useContext(LoginContext); const submit = () => { Axios.post("http://localhost:3001/login", data).then((res) => { localStorage.setItem("bankDetails", res.data[0].acc_no); setisValid(true); }; useEffect(()=>{ if(isValid){ navigate("/home") } },[isValid])