Learn the concept
Hooks
A useFetch hook encapsulates data fetching logic with loading, error, and data states. It uses AbortController to handle cleanup and race conditions when the URL changes or the component unmounts, and can support refetch and basic caching.
Why useFetch:
Core Implementation:
data, error, loadinguseEffect to trigger the fetch when the URL changesAbortController to cancel in-flight requests on cleanup{ data, error, loading } and optionally a refetch functionRace Condition Handling:
AbortError must be caught and ignored (it is expected behavior)Refetch Capability:
refetch function that re-triggers the fetch imperativelyComparison with Libraries:
import { useState, useEffect } from 'react';
function useFetch(url, options = {}) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (!url) {
setData(null);
setLoading(false);
return;
}
const controller = new AbortController();
async function fetchData() {
setLoading(true);
setError(null);
try {
const response = await fetch(url, {
...options,
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const json = await response.json();
setData(json);
} catch (err) {
// Ignore abort errors — they are expected on cleanup
if (err.name !== 'AbortError') {
setError(err);
}
} finally {
if (!controller.signal.aborted) {
setLoading(false);
}
}
}
fetchData();
// Cleanup: abort fetch on unmount or URL change
return () => controller.abort();
}, [url]);
return { data, error, loading };
}Fetching multiple API endpoints to populate dashboard widgets, with each widget independently showing loading and error states
Fetching paginated data as the user scrolls, using useFetch with a dynamic URL that includes the current page or cursor parameter
Fetching remote feature flag configuration on app startup, with the hook managing the loading state while the flags are resolved
Build a React app that uses useFetch to search GitHub repositories by username with pagination and proper race condition handling
Extend useFetch to implement stale-while-revalidate: serve cached data instantly while fetching fresh data in the background
Builds on the useFetch concept with a production-grade solution adding caching, deduplication, pagination, optimistic updates, and background refetching