Powered by GPT-4o
import { useState, useEffect, useCallback } from "react";
interface FetchOptions {
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
body?: Record<string, unknown>;
headers?: Record<string, string>;
}
interface UseFetchReturn<T> {
data: T | null;
loading: boolean;
error: string | null;
refetch: () => void;
}
/**
* Custom hook for data fetching with loading and error states.
* Supports GET, POST, PUT, DELETE, and PATCH methods.
*
* @param url - The API endpoint URL
* @param options - Optional fetch configuration
*/
export function useFetch<T = unknown>(
url: string,
options: FetchOptions = {}
): UseFetchReturn<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchData = useCallback(async () => {
try {
setLoading(true);
setError(null);
const response = await fetch(url, {
method: options.method ?? "GET",
headers: {
"Content-Type": "application/json",
...options.headers,
},
body: options.body ? JSON.stringify(options.body) : undefined,
});
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.message : "An unknown error occurred");
} finally {
setLoading(false);
}
}, [url, options.method]);
useEffect(() => {
fetchData();
}, [fetchData]);
return { data, loading, error, refetch: fetchData };
}