useFetch Hook
April 30, 2025
Fetching data is a core part of most React applications. This hook encapsulates the common pattern of loading, error handling, and data management.
import { useState, useEffect } from 'react';
interface UseFetchResult<T> {
data: T | null;
loading: boolean;
error: Error | null;
refetch: () => void;
}
export function useFetch<T>(
url: string,
options?: RequestInit
): UseFetchResult<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const fetchData = async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
setData(result);
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'));
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchData();
}, [url]);
return { data, loading, error, refetch: fetchData };
}
How It Works
- Manages three states:
data,loading, anderror. - Automatically fetches when the URL changes.
- Provides a
refetchfunction to manually trigger a new request. - Handles HTTP errors and network failures.
Example Usage
function UserProfile({ userId }: { userId: string }) {
const { data, loading, error, refetch } = useFetch<User>(
`/api/users/${userId}`
);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!data) return null;
return (
<div>
<h1>{data.name}</h1>
<button onClick={refetch}>Refresh</button>
</div>
);
}
With POST Request
function CreatePost() {
const { data, loading, error, refetch } = useFetch<Post>(
'/api/posts',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: 'New Post' }),
}
);
}
Use Cases
- Fetching user data
- Loading blog posts
- Retrieving API responses
- Fetching configuration
- Loading dashboard data
Notes
- Automatically refetches when the URL changes.
- Consider adding request cancellation for cleanup.
- For more advanced features (caching, retries), consider libraries like
react-queryorswr. - The
refetchfunction allows manual refresh without changing the URL.
A simple, reusable hook that handles the common data fetching pattern with built-in loading and error states.