Los hooks personalizados son una de las herramientas más útiles de React cuando una aplicación comienza a crecer. Permiten extraer lógica reutilizable de los componentes y mantener el código más organizado, fácil de mantener y de probar.
Un hook personalizado es simplemente una función de JavaScript cuyo nombre comienza con use y que puede utilizar otros hooks de React como useState, useEffect o useContext.
Por ejemplo, imaginemos que varias partes de nuestra aplicación necesitan controlar un estado de carga. En lugar de repetir la misma lógica, podemos crear un hook:
import { useState } from "react";
function useLoading() {
const [loading, setLoading] = useState(false);
return { loading, setLoading };
}
export default useLoading;
Después podemos utilizarlo desde cualquier componente:
function Usuarios() {
const { loading, setLoading } = useLoading();
return (
<div>
{loading ? "Cargando..." : "Usuarios"}
</div>
);
}
Sin embargo, los hooks personalizados resultan especialmente interesantes cuando encapsulan procesos completos.
Hooks para consumir APIs
Un caso muy común en proyectos reales es crear un hook para obtener información desde una API:
import { useEffect, useState } from "react";
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(response => {
if (!response.ok) throw new Error("Error en la petición");
return response.json();
})
.then(data => setData(data))
.catch(error => setError(error))
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
Ahora cualquier componente puede reutilizar esta lógica:
function Productos() {
const { data, loading, error } =
useFetch("https://api.example.com/productos");
if (loading) return <p>Cargando productos...</p>;
if (error) return <p>Ocurrió un error</p>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
La ventaja principal es que el componente se concentra en mostrar la información, mientras que el hook se encarga de la lógica relacionada con la petición.
¿Cuándo crear un hook?
No es necesario convertir cada pequeña función en un hook. Lo recomendable es hacerlo cuando existe lógica que se repite entre varios componentes o cuando una determinada funcionalidad es suficientemente compleja como para separarla.
Algunos ejemplos habituales son:
useFetch()para consumir APIs.useAuth()para manejar autenticación.useLocalStorage()para trabajar con almacenamiento local.useForm()para controlar formularios.useDebounce()para retrasar búsquedas.useWindowSize()para detectar cambios en el tamaño de pantalla.
En proyectos grandes, esta separación ayuda a evitar componentes gigantes y facilita la reutilización.
Una buena práctica
Los hooks personalizados deben encargarse principalmente de lógica y estado, no de la presentación visual. De esta manera, un mismo hook puede utilizarse en diferentes pantallas aunque cada una tenga un diseño completamente distinto.
En conclusión, los hooks personalizados permiten transformar lógica repetitiva en funcionalidades reutilizables. Cuando una aplicación React crece, aprender a identificar qué lógica puede convertirse en un hook es fundamental para conseguir un código más limpio, escalable y fácil de mantener.

