Cuando construyes una aplicación web con React, llega un momento en el que necesitas que la información sobreviva a recargas de página, cierres de ventana e incluso apagados del equipo. localStorage es la herramienta que todos los navegadores modernos ofrecen para lograr exactamente eso, sin necesidad de un back end.
¿Qué es localStorage y por qué es útil en el front end?
Las aplicaciones web se dividen en front end y back end. El front end se encarga de la parte visual y de la interacción con el usuario, mientras que el back end gestiona validaciones, autenticación y bases de datos. Antes de aprender a hacer llamados a APIs desde React, es posible guardar y recuperar información directamente en el navegador gracias a localStorage [0:35].
Esta herramienta permite almacenar datos que persisten sin importar si el usuario cierra la pestaña, recarga la página o apaga la computadora. La información seguirá disponible cuando vuelva, incluso una semana después.
¿Cómo funcionan setItem y getItem?
localStorage expone dos métodos fundamentales:
localStorage.setItem(clave, valor): guarda un valor asociado a una clave [1:28].
localStorage.getItem(clave): recupera el valor almacenado bajo esa clave [2:50].
Una restricción importante: localStorage solo puede guardar texto. No acepta objetos, arrays, números ni booleanos directamente.
¿Cómo convertir objetos a texto y viceversa con JSON?
Para sortear la limitación de solo texto se utilizan dos métodos del objeto JSON [1:50]:
JSON.stringify(): transforma cualquier objeto o array de JavaScript en un string.
JSON.parse(): convierte ese string de vuelta a un objeto o array de JavaScript.
Por ejemplo, un array con un objeto { text: "...", completed: false } pasa por JSON.stringify para guardarse en localStorage, y luego por JSON.parse al recuperarse para volver a ser JavaScript utilizable.
¿Cómo integrar localStorage con el estado de React?
Dentro del componente App.js, en lugar de mantener una lista de todos escrita a mano (hardcoded), se puede inicializar el estado con los datos almacenados en localStorage [4:05].
El proceso se divide en dos escenarios:
- Usuario nuevo: no existe información previa en localStorage. Se crea un array vacío con
localStorage.setItem pasándole JSON.stringify([]) y se usa ese array vacío como estado inicial [5:40].
- Usuario recurrente: ya hay todos guardados. Se recuperan con
getItem, se transforman con JSON.parse y se envían como valor por defecto a useState [5:15].
El condicional que determina cuál camino seguir verifica si el valor retornado por getItem es falsy (null, undefined, false o string vacío). Si no existe nada, se entra al flujo de usuario nuevo.
Un detalle que puede generar errores: al guardar el array vacío inicial, hay que recordar pasarlo por JSON.stringify. Sin esa conversión, localStorage almacena un string vacío en lugar de "[]" [6:45].
¿Cómo persistir cambios al completar o eliminar todos?
Recuperar datos al cargar la aplicación es solo la mitad del trabajo. Si un usuario completa o elimina un todo y recarga la página, los cambios se pierden si no se guardan de vuelta en localStorage [8:30].
La solución es crear una función puente llamada saveTodos que actúa como intermediaria entre las funciones completeTodo / deleteTodo y el estado de React [9:10]:
javascript
const saveTodos = (newTodos) => {
const stringifiedTodos = JSON.stringify(newTodos);
localStorage.setItem('TODOS_V1', stringifiedTodos);
setTodos(newTodos);
};
Esta función hace tres cosas en orden:
- Convierte el nuevo array de todos a texto con
JSON.stringify.
- Guarda ese texto en localStorage bajo la clave correspondiente.
- Actualiza el estado local del componente con
setTodos, enviándole el array original de JavaScript, no el string.
De esta manera, cada acción del usuario queda persistida en localStorage y reflejada en la interfaz sin necesidad de recargar [10:25].
Un patrón interesante que se menciona es el versionado de claves en localStorage, similar a como las APIs versionan sus endpoints. Usar nombres como TODOS_V1 permite introducir cambios estructurales en el futuro sin romper datos de versiones anteriores [4:30].
El siguiente paso natural para mantener el componente limpio y legible es extraer toda esta lógica en un custom hook, un React hook personalizado que encapsule la interacción con localStorage. ¿Ya has creado tus propios hooks? Comparte tu experiencia en los comentarios.