JAVASCRIPT
useApiFetch Hook for Robust Data Fetching in React
A custom React hook to simplify API data fetching, handling loading states, errors, and data caching with a clean, reusable interface for any REST API endpoint.
import React, { useState, useEffect, useCallback } from 'react';
const useApiFetch = (url, options = {}) => {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const fetchData = useCallback(async () => {
setIsLoading(true);
setError(null);
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const json = await response.json();
setData(json);
} catch (e) {
setError(e);
} finally {
setIsLoading(false);
}
}, [url, JSON.stringify(options)]); // Dependency on JSON.stringify(options) for deep comparison
useEffect(() => {
fetchData();
}, [fetchData]);
return { data, isLoading, error, refetch: fetchData };
};
export default useApiFetch;
// Example Usage:
// function MyComponent() {
// const { data, isLoading, error, refetch } = useApiFetch('https://api.example.com/items');
// if (isLoading) return <div>Loading...</div>;
// if (error) return <div>Error: {error.message}</div>;
// return (
// <div>
// <h1>Items</h1>
// <button onClick={refetch}>Refetch Data</button>
// <ul>
// {data && data.map(item => (
// <li key={item.id}>{item.name}</li>
// ))}
// </ul>
// </div>
// );
// }
How it works: This React `useApiFetch` hook centralizes the logic for making API calls. It manages three key states: `data` (the fetched result), `isLoading` (a boolean indicating if the request is in progress), and `error` (any error encountered). The `fetchData` function is memoized with `useCallback` and executed via `useEffect` when the component mounts or `url`/`options` change. It handles network errors and non-OK HTTP responses, providing a robust wrapper for `fetch`. The hook also returns a `refetch` function, allowing manual data refreshing.