58 lines
1.4 KiB
TypeScript
58 lines
1.4 KiB
TypeScript
import { useEffect } from "preact/hooks";
|
|
import { signal } from "@preact/signals";
|
|
|
|
export function useFetch<T>(
|
|
url: string,
|
|
options?: FetchOptions,
|
|
): {
|
|
data: T | null;
|
|
loading: boolean;
|
|
error: Error | null;
|
|
refetch: (newURL?: string, newOptions?: FetchOptions) => void;
|
|
} {
|
|
const data = signal<T | null>(null);
|
|
const loading = signal<boolean>(true);
|
|
const error = signal<Error | null>(null);
|
|
|
|
useEffect(() => {
|
|
fetch(url, options)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error("Failed to fetch data");
|
|
}
|
|
return response.json();
|
|
})
|
|
.then((resp) => (data.value = resp))
|
|
.catch((err) => (error.value = err))
|
|
.finally(() => (loading.value = false));
|
|
}, [url, options]);
|
|
|
|
const refetch = (newURL?: string, newOptions?: FetchOptions) => {
|
|
loading.value = true;
|
|
error.value = null;
|
|
fetch(newURL || url, newOptions || options)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error("Failed to fetch data");
|
|
}
|
|
return response.json();
|
|
})
|
|
.then((resp) => (data.value = resp))
|
|
.catch((err) => (error.value = err))
|
|
.finally(() => (loading.value = false));
|
|
};
|
|
|
|
return {
|
|
data: data.value,
|
|
loading: loading.value,
|
|
error: error.value,
|
|
refetch,
|
|
};
|
|
}
|
|
|
|
export interface FetchOptions {
|
|
method: "GET" | "POST" | "PUT" | "DELETE";
|
|
headers: Record<string, string>;
|
|
body: string;
|
|
}
|