Introducción
Desde la versión 16.8, React ha revolucionado la manera de manejar la lógica de los componentes al introducir los custom hooks. Estas poderosas funciones nos permiten encapsular y reutilizar lógica de manera eficiente y elegante. Para aquellos que no estén familiarizados con los hooks en React, aquí va una breve explicación.
Los hooks en React son funciones de JavaScript cuyo nombre comienza con use
y que pueden invocar otros hooks de React dentro de ellas. Permiten manejar estados y efectos secundarios en componentes funcionales, eliminando la necesidad de usar clases. Un custom hook es un hook personalizado que creamos nosotros mismos, extendiendo la funcionalidad básica que ofrece React.
En este post, exploraremos cómo crear nuestros propios custom hooks con ejemplos prácticos y útiles para diferentes escenarios, mostrando cómo estos pueden mejorar la organización y reutilización de la lógica en nuestras aplicaciones React.
Ventajas de Usar Custom Hooks de React
- Reutilización: Permiten reutilizar lógica compleja en diferentes componentes sin duplicación de código.
- Código Más Limpio: Ayudan a mantener los componentes más limpios y enfocados en la UI, delegando la lógica a los hooks.
- Mantenibilidad: Facilitan el mantenimiento del código al tener lógica desacoplada y bien organizada.
- Abstracción: Permiten crear abstracciones de lógica compleja, haciendo que los componentes sean más fáciles de entender y de probar.
- Flexibilidad: Pueden aceptar parámetros y devolver resultados personalizados, permitiendo crear soluciones flexibles y adaptables a diferentes necesidades.
Algunos ejemplos de custom hooks
useFetch: hacer peticiones http fácil y rápido
Uno de mis hooks favoritos es el que me permite hacer llamadas http de manera fácil y sencilla, ya que este proceso lo solemos hacer una y otra vez. Este hook suelo llamarlo useFetch
import { useState, useEffect } from 'react';
const useFetch = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const result = await response.json();
setData(result);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
}
export default useFetch;
Como se puede ver, haciendo uso del hook de React useState, puedo guardarme aquellos valores que siempre suelo tratar cuando hago una llamada a una API, los datos, los errores y si está o no haciendo la llamada.
Si este hook lo tenemos en un fichero aparte, su uso sería tan sencillo como hacer escribir lo siguiente en nuestro código.
const { data, loading, error } = useFetch('https://api.example.com/data');
Así podríamos hacer uso de él en un ejemplo como el siguiente
import useFetch from './useFetch';
const App = () => {
const { data, loading, error } = useFetch('https://api.example.com/data');
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>Data:</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
export default App;
useLocalStorage: guardar datos en el local storage del navegador
Otro de los hooks que uso frecuentemente es uno que facilita la manipulación del local storage del navegador. Aunque no es una operación que se realice todos los días, contar con un hook como el que te muestro a continuación puede ahorrarte mucho tiempo y esfuerzo cuando necesites interactuar con el almacenamiento local.
import { useState } from 'react';
const useLocalStorage = (key, initialValue) => {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
const setValue = value => {
try {
const valueToStore = value instanceof Function ? value(storedValue) : value;
setStoredValue(valueToStore);
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
console.error(error);
}
};
return [storedValue, setValue];
}
export default useLocalStorage;
Como se puede apreciar, este hook es algo más complejo por lo que siempre es útil tenerlo a mano y no tener que preocuparse cada vez de ir a la documentación a ver como se trabaja con el local storage
Un uso de este hook, aunque muy simple, nos hace ver la facilidad de uso que tiene.
import useLocalStorage from './useLocalStorage';
const App = () => {
const [name, setName] = useLocalStorage('name', 'John Doe');
return (
<div>
<h1>Hello, {name}!</h1>
<input
type="text"
value={name}
onChange={e => setName(e.target.value)}
/>
</div>
);
}
export default App;
Conclusión
Crear custom hooks en React es una manera poderosa de mantener tu código limpio, reutilizable y fácil de entender. Los ejemplos anteriores muestran cómo puedes encapsular lógica para manejar localStorage
y realizar peticiones HTTP. Experimenta con estos hooks y crea tus propios hooks personalizados para optimizar tu código y mejorar la mantenibilidad de tus aplicaciones.
Recuerda que los custom hooks no son solo una herramienta para reutilizar código, sino también una manera de mejorar la arquitectura y la calidad de tu aplicación. ¡Explora, experimenta y disfruta de la potencia de los custom hooks en React!