Estoy tratando de hacer un sistema de autenticación. Los usuarios pueden iniciar y cerrar sesión a través de la barra de navegación superior. El nombre de usuario se almacenará en el almacenamiento local. Puedo encontrar 'usuario' en mi almacenamiento local después de iniciar sesión, y desaparece después de cerrar sesión.
Pero parece que useEffect no funciona correctamente, por lo que la barra superior no cambia en consecuencia. Cualquier ayuda es apreciada.
function App() { const [isLoggedIn, setIsLoggedIn] = useState(true); useEffect(() => { function checkUserData() { const user = localStorage.getItem("user"); if (user) { setIsLoggedIn(true); } } window.addEventListener("storage", checkUserData); return () => { window.removeEventListener("storage", checkUserData); }; }, []); return ( <Router> <div className="container"> <TopBar logout={() => { localStorage.removeItem("user"); }} loginStatus={isLoggedIn} /> <Routes> <Route path="/" element={<Home />} /> <Route path="/sign-in/" element={ <SignIn toggleLoggedIn={(user) => { localStorage.setItem("user", user); }} /> } /> <Footer /> </div> </Router> ); } function TopBar(props) { return ( <div> <AppBar> <Toolbar > <Box /> <Box> {props.loginStatus ? ( <Link href="/" onClick={props.logout} component="button" > {"Sign Out"} </Link> ) : ( <> <Link href="/sign-in/" > {"Sign In"} </Link> <Link href="/sign-up/" > {"Sign Up"} </Link> </> )} </Box> </Toolbar> </AppBar> <Toolbar /> </div> ); }Cambie las funciones de cierre de logout y toggleLoggedIn como se muestra a continuación. dispach el evento de storage , porque normalmente, un cambio de storage no se nota en el mismo documento que está realizando los cambios.
() => { localStorage.removeItem("user"); window.dispatchEvent(new Event("storage")); } (user) => { localStorage.setItem("user", user); window.dispatchEvent(new Event("storage")); } Luego cambie checkUserData como se muestra a continuación, para manejar el caso else , y cambie isLoggedIn a false .
function checkUserData() { const user = localStorage.getItem("user"); if (user) { setIsLoggedIn(true); }else{ setIsLoggedIn(false); } } Y finalmente, cambie su definición de isLoggedIn como se muestra a continuación, de modo que configure el estado de inicio de sesión dinámicamente de acuerdo con lo que hay en el storage de la visita anterior:
const [isLoggedIn, setIsLoggedIn] = useState(localStorage.getItem("user") ? true : false);No cambia el booleano isLoggedIn. Entonces la barra de navegación no sabe cuándo actualizar.
Tienes que hacer algo como esto:
if (user) { setIsLoggedIn(true); } else { setIsLoggedIn(false); }o algo en desmontar como
useEffect(() => {return () => setIsLoggedIn(false)}, []);No tengo el contexto de su aplicación, pero la lógica principal es pasar este valor booleano a falso cuando el usuario no ha iniciado sesión.
Además, le recomiendo que externalice esta lógica a través de un gancho, por ejemplo, "useAuthentication()". Entonces la lógica está separada del renderizado.
Note: The storage event is only triggered when a window other than itself makes the changes.
Encontré esto en https://www.w3schools.com/jsref/event_storage_url.asp