Entonces, estoy tratando de verificar si localStorage está vacío o no, y si es así, quiero que mi estado cambie de inmediato.
He creado este estado y estoy configurando este estado inicialmente vacío
const [isLoggedIn, setLogin] = useState();Luego estoy usando useEffect hook para obtener un elemento de localStorage si algo tiene en localStorage, establecerá mi estado como verdadero, de lo contrario, falso
useEffect(() => { if (localStorage.getItem("info") !== null) { setLogin(true); } else { setLogin(false); } }, []);Entonces, cuando agrego algo o lo elimino de mi almacenamiento local, no funciona y necesito actualizar mi página para que funcione.
He creado un espacio aislado de código para comprobar lo que está pasando, eche un vistazo y ayude a que funcione.
https://codesandbox.io/s/great-mclaren-vypyo?file=/src/App.js:164-304
Sus comandos de almacenamiento local parecen correctos. Pero el problema es que no está revisando el almacenamiento cada vez. Debe tener una variable de estado que pueda usar para indicar que algo ha cambiado y que el almacenamiento debe verificarse nuevamente.
import "./styles.css"; import React, { useState, useRef, useEffect } from "react"; export default function App() { const [isLoggedIn, setLogin] = useState(); const [change, setChange] = useState(false); useEffect(() => { if (localStorage.getItem("info") !== null) { setLogin(true); } else { setLogin(false); } }, [change]); console.log(isLoggedIn); return ( <div className="App"> {isLoggedIn ? ( <h1>LocalStorage has something</h1> ) : ( <h2>LocalStorage has nothing</h2> )} <button onClick={() => { localStorage.setItem("info", "true"); setChange((change) => !change); }} > Add to Local </button> <button onClick={() => { localStorage.removeItem("info"); setChange((change) => !change); }} > Remove to Local </button> </div> ); } En el código anterior, el change cambia cuando se ejecuta uno de sus comandos de almacenamiento. Podrías haber tenido un contador o cualquier otra cosa también. El objetivo principal es verificar el almacenamiento cada vez que cambia cosas. De esta manera, puede tener múltiples comandos de almacenamiento (incluso más de 2) y luego puede verificar su almacenamiento después de cada cambio.
Otro enfoque simple podría ser simplemente configurar el estado de inicio de sesión dentro de sus funciones donde ejecuta los comandos localStorage :
import "./styles.css"; import React, { useState, useRef, useEffect } from "react"; export default function App() { const [isLoggedIn, setLogin] = useState(); useEffect(() => { if (localStorage.getItem("info") !== null) { setLogin(true); } else { setLogin(false); } }, [isLoggedIn]); console.log(isLoggedIn); return ( <div className="App"> {isLoggedIn ? ( <h1>LocalStorage has something</h1> ) : ( <h2>LocalStorage has nothing</h2> )} <button onClick={() => { localStorage.setItem("info", "true"); setLogin(true); }} > Add to Local </button> <button onClick={() => { localStorage.removeItem("info"); setLogin(false); }} > Remove to Local </button> </div> ); }Ahora tiene una variable de estado menor, pero manipulará directamente el estado de inicio de sesión desde sus botones.
Si no establece el elemento ("info"), quiero decir que si "info" no existe en localStorage, obtendrá "nulo" y su código funcionará. Pero si configura algo en "info" en localStorage, por ejemplo, si hace localStorage.setItem (""), entonces no obtendrá un valor nulo, obtendrá una cadena vacía. Por lo tanto su código debe ser:
useEffect(() => { if (localStorage.getItem("info") !== null || localStorage.getItem("info") !== "") { setLogin(true); } else { setLogin(false); } }, []);si usa una matriz en lugar de una cadena en "info", entonces
useEffect(() => { if (localStorage.getItem("info") !== null || JSON.parse(localStorage.getItem("info")).length > 0) { setLogin(true); } else { setLogin(false); } }, []);El problema es que al cargar la página, está configurando la existencia/no existencia del elemento localStorage en el estado del componente. Sin embargo, cuando se realiza una acción ( setItem / removeItem ), no está actualizando el estado. La forma sencilla de lograrlo es actualizar el estado en el detector de eventos.
<button onClick={() => { localStorage.setItem("info", "true"); setLogin(true); }}>Add to Local</button> <button onClick={() => { localStorage.removeItem("info"); setLogin(false); }}>Remove to Local</button>Aquí hay un enlace de sandbox bifurcado y actualizado.