Consumir APIs es una tarea común en cualquier aplicación React.
Sin embargo, manejar estados como loading, error, o incluso reintentos puede volverse complicado y repetitivo. En este post, aprenderás cómo usar un hook llamado useFetch que simplifica este proceso.
useFetch?useFetch es un custom hook de React diseñado para simplificar las solicitudes HTTP a APIs.
Este hook encapsula toda la lógica necesaria para manejar solicitudes, respuestas y errores, permitiendo que tus componentes sean más limpios y fáciles de leer.
useFetchfunction MiComponente() {
const { data, loading, error, reload } = useFetch('https://api.vercel.app/blog');
if (loading) return <p>Cargando...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
{data && <pre>{JSON.stringify(data)}</pre>}
<button onClick={reload}>Recargar Datos</button>
</div>
);
} El componente MiComponente usa un hook useFetch que además de gestionar estados como data, loading y error, incluye una función reload para volver a realizar la solicitud. Muestra un mensaje mientras los datos se cargan (loading) o un error si ocurre algo mal. Una vez que los datos están disponibles (data), los muestra formateados con JSON.stringify y ofrece un botón que permite recargar los datos llamando a la función reload.
useFetchimport { useState, useEffect } from 'react';
export function useFetch(url, options) {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
setError(null);
try {
const response = await fetch(url, options);
if (!response.ok) throw new Error(`Error: ${response.status}`);
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
};
if (url) fetchData();
}, [url, options]);
return { data, isLoading, error };
} Este hook personalizado useFetch realiza solicitudes HTTP de forma sencilla.
Usa useState para gestionar el estado de los datos (data), la carga (isLoading) y los errores (error). Dentro de un useEffect, define una función asíncrona que realiza la solicitud con fetch, manejando posibles errores y actualizando los estados según el resultado. Finalmente, retorna los estados para que el componente que lo use acceda a la información.
useFetchPuedes agregar funcionalidades extra como reintentos o control de intervalos:
export function useFetchWithRetry(url, options, retries = 3) {
const { data, isLoading, error } = useFetch(url, options);
useEffect(() => {
let attempts = 0;
const retryFetch = () => {
if (error && attempts < retries) {
attempts++;
useFetch(url, options);
}
};
retryFetch();
}, [url, options, error, retries]);
return { data, isLoading, error };
} El hook useFetchWithRetry extiende useFetch añadiendo lógica para reintentar solicitudes fallidas.
Usa useEffect para controlar reintentos, incrementando un contador (attempts) cada vez que ocurre un error, hasta alcanzar el límite definido por retries. Si no hay error o se alcanzan los intentos máximos, retorna los mismos estados (data, isLoading, error) de useFetch.
function CreateUser() {
const [userData, setUserData] = useState({});
const { loading, error, fetchData } = useFetch(
'https://api.example.com/users',
{
method: 'POST',
body: JSON.stringify(userData)
}
);
const handleSubmit = () => {
fetchData()
.then(response => {
// Manejar respuesta
});
};
} Este ejemplo utiliza useFetch para realizar una solicitud POST a una API y crear un usuario.
El estado userData almacena los datos del usuario a enviar, mientras que fetchData es una función del hook que dispara la solicitud.
Al llamar a handleSubmit, se ejecuta fetchData con las opciones especificadas (método y cuerpo de la solicitud) y luego se maneja la respuesta en una promesa.
Demuestra cómo usar useFetch en un componente funcional.
import React from 'react';
import { useFetch } from './useFetch';
function Posts() {
const { data, isLoading, error } = useFetch('https://jsonplaceholder.typicode.com/posts');
if (isLoading) return <p>Cargando posts...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<h1>Lista de Posts</h1>
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
export default Posts; El componente Posts utiliza el hook useFetch para consumir una API que devuelve una lista de publicaciones.
Muestra un mensaje de “Cargando” mientras la solicitud está en progreso (isLoading) y un mensaje de error si ocurre un problema.
Una vez que los datos están disponibles (data), renderiza un listado de títulos en una lista desordenada.
useFetch es una herramienta poderosa que simplifica el consumo de APIs, dejando a los desarrolladores más tiempo para concentrarse en la lógica de negocio y en la experiencia del usuario.