Skip to content

Instantly share code, notes, and snippets.

@michael-lynch
Last active July 4, 2024 21:12
Show Gist options
  • Select an option

  • Save michael-lynch/a291d4e25c52ad28f8334059bdf349f6 to your computer and use it in GitHub Desktop.

Select an option

Save michael-lynch/a291d4e25c52ad28f8334059bdf349f6 to your computer and use it in GitHub Desktop.
// react
import { useCallback, useEffect, useRef, useState } from 'react';
// props
export interface UseFetchParams {
isEnabled?: boolean;
isLazy?: boolean;
onComplete?: () => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onError?: (error: any) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onSuccess?: (data: any) => void;
options?: object;
url?: string;
}
export const useFetch = ({
isEnabled = true,
isLazy = false,
onComplete,
onError,
onSuccess,
options = {},
url,
}: UseFetchParams) => {
// state
const [error, setError] = useState<unknown>(null);
const [isLoading, setIsLoading] = useState(false);
// refs
const refOnComplete = useRef(onComplete);
const refOnError = useRef(onError);
const refOnSuccess = useRef(onSuccess);
const refOptions = useRef(options);
const refUrl = useRef(url);
const fetchRequest = useCallback(async (u = refUrl.current, o = refOptions.current) => {
// set loading
setIsLoading(true);
try {
if (!u) {
throw new Error('A URL is required.');
}
const req = await fetch(u, {
...o,
});
const res = await req.json();
if (res.error) {
throw new Error('Unknown error', { cause: res.error });
}
if (refOnSuccess.current) {
refOnSuccess.current(res);
}
return res;
} catch (error) {
if (refOnError.current) {
refOnError.current(error);
}
setError(error);
} finally {
if (refOnComplete.current) {
refOnComplete.current();
}
setIsLoading(false);
}
}, []);
const refetch = useCallback(() => {
fetchRequest();
}, [fetchRequest]);
// update url on change
useEffect(() => {
refUrl.current = url;
}, [url]);
useEffect(() => {
if (!isLazy && isEnabled) {
fetchRequest();
}
}, [fetchRequest, isEnabled, isLazy]);
return {
error,
fetchRequest,
isLoading,
refetch,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment