Contenido del curso

Herramientas avanzadas: escalabilidad, organización y persistencia

Custom Hook para Local Storage en React

Resumen

Aprende a construir un Custom Hook en React llamado useLocalStorage para abstraer la lógica de persistencia de datos y mantener tu componente App limpio, reutilizable y fácil de mantener.

Cuando mezclas la lógica de tus todos con llamadas a Local Storage, validaciones de JSON.parse, JSON.stringify y funciones actualizadoras, tu componente se vuelve difícil de leer. La solución elegante es mover toda esa lógica a un hook propio que cualquier componente pueda consumir.

¿Qué es un Custom Hook en React y por qué empieza con use?

Un Custom Hook es una función de JavaScript que encapsula lógica reutilizable basada en los hooks oficiales de React, como useState, useEffect, useContext o useCallback.

La convención que React te pide seguir, de forma opcionalmente obligatoria, es que el nombre empiece siempre con la palabra use. Así, tanto tú como cualquier persona que lea tu código sabe inmediatamente qué función es un hook y cuál es una función normal de la aplicación [02:14].

¿Qué es un Custom Hook? Es una función que empieza con use y agrupa lógica reutilizable de React, como estados o efectos, para que la consumas desde cualquier componente sin repetir código.

¿Cómo abstraer Local Storage en un Custom Hook reutilizable?

La idea es que tu componente App no llame directamente a Local Storage. Toda la lógica de leer, escribir, parsear y actualizar se mueve al hook useLocalStorage, y el componente solo consume el estado final.

Dentro del hook creas un estado interno con React.useState, pero en lugar de llamarlo todos lo llamas item, porque Local Storage trata todo su contenido como items. Así puedes guardar cualquier cosa: todos, usuarios, configuraciones, lo que sea.

¿Qué parámetros recibe useLocalStorage?

Para que el hook sea verdaderamente reutilizable, recibe dos argumentos clave [05:32]:

  • itemName: el nombre clave bajo el cual se guarda la información en Local Storage. Reemplaza el string fijo TODOS_V1.
  • initialValue: el estado inicial por defecto. Puede ser un array vacío, un string, un número, un booleano o lo que necesites.

Con estos dos parámetros, una misma función sirve para guardar todos, usuarios o cualquier otro tipo de dato sin reescribir lógica.

¿Qué debe retornar el Custom Hook?

El hook retorna un array con dos elementos: el estado actual del item y una función saveItem que actualiza tanto el estado de React como el contenido en Local Storage [08:45].

No retornas el setItem original de useState, porque ese solo actualizaría React. La función saveItem hace ambas cosas a la vez: persiste en Local Storage y refresca el estado interno.

js function useLocalStorage(itemName, initialValue) { const localStorageItem = localStorage.getItem(itemName); let parsedItem;

if (!localStorageItem) { localStorage.setItem(itemName, JSON.stringify(initialValue)); parsedItem = initialValue; } else { parsedItem = JSON.parse(localStorageItem); }

const [item, setItem] = React.useState(parsedItem);

const saveItem = (newItem) => { localStorage.setItem(itemName, JSON.stringify(newItem)); setItem(newItem); };

return [item, saveItem]; }

¿Cómo se consume el Custom Hook desde el componente App?

En lugar de llamar a React.useState, ahora llamas directamente a tu hook. Como retorna un array, puedes nombrar las variables como prefieras, igual que con useState [10:50].

js const [todos, saveTodos] = useLocalStorage('TODOS_V1', []);

El primer argumento es el nombre clave en Local Storage; el segundo es el estado inicial. El resto de funciones como completeTodo, deleteTodo y addTodo siguen funcionando exactamente igual, porque siguen llamando a saveTodos por dentro.

¿Por qué retornar un array y no un objeto? Con un array puedes renombrar las variables al desestructurar. Con un objeto, estarías obligado a usar los nombres exactos de las propiedades.

¿Cuándo vale la pena crear un Custom Hook?

No existe una regla fija de "a partir de tantas líneas, crea un hook". Lo que tienes es criterio, y ese criterio se forma con práctica [13:20].

Algunas señales útiles para decidir:

  • La lógica de tu componente mezcla varios temas distintos y cuesta leerla.
  • Vas a reutilizar la misma lógica en otro componente o proyecto.
  • Quieres separar responsabilidades para que un cambio en Local Storage no afecte la lógica de negocio.

Abstraer demasiado pronto también te puede quitar tiempo. Si la lógica es simple y solo se usa una vez, quizá no valga la pena.

¿Qué ganas con esta abstracción?

La aplicación se ve exactamente igual para los usuarios. La persistencia funciona, los todos se completan y se eliminan como antes. Lo que mejora es tu developer experience: el componente App ahora solo contiene lógica de todos, y toda la persistencia vive en un archivo separado, fácil de mantener y modificar.

Si alguien de tu equipo necesita tocar algo de Local Storage, sabe exactamente dónde buscar. Y si necesita ajustar los todos, no se topa con código de persistencia que lo distraiga.

¿Ya tienes en mente qué otra lógica de tus proyectos podrías mover a un Custom Hook? Cuéntame en los comentarios qué hook propio te gustaría crear.