61 lines
1.5 KiB
TypeScript
61 lines
1.5 KiB
TypeScript
/**
|
|
* File: useFetch.ts
|
|
* Created by: AI Assistant
|
|
* Date: 2025-11-29
|
|
* Purpose: Custom hook for data fetching
|
|
* Part of: kreatiVortex - Platform Pembelajaran Tari Online
|
|
*/
|
|
|
|
import { useState, useEffect } from 'react';
|
|
|
|
interface FetchOptions {
|
|
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
headers?: Record<string, string>;
|
|
body?: any;
|
|
}
|
|
|
|
interface FetchResult<T> {
|
|
data: T | null;
|
|
loading: boolean;
|
|
error: Error | null;
|
|
refetch: () => Promise<void>;
|
|
}
|
|
|
|
export function useFetch<T>(url: string, options?: FetchOptions): FetchResult<T> {
|
|
const [data, setData] = useState<T | null>(null);
|
|
const [loading, setLoading] = useState<boolean>(true);
|
|
const [error, setError] = useState<Error | null>(null);
|
|
|
|
const fetchData = async () => {
|
|
setLoading(true);
|
|
setError(null);
|
|
try {
|
|
const response = await fetch(url, {
|
|
method: options?.method || 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
...options?.headers,
|
|
},
|
|
body: options?.body ? JSON.stringify(options.body) : undefined,
|
|
credentials: 'include',
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Error: ${response.status} ${response.statusText}`);
|
|
}
|
|
|
|
const result = await response.json();
|
|
setData(result.data || result);
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err : new Error('An unknown error occurred'));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
fetchData();
|
|
}, [url]);
|
|
|
|
return { data, loading, error, refetch: fetchData };
|
|
} |