Skip to content

Instantly share code, notes, and snippets.

@IrvingArmenta
Last active October 12, 2022 05:38
Show Gist options
  • Save IrvingArmenta/45585cf58c1a8b4b3365bf8a61c4ff02 to your computer and use it in GitHub Desktop.
Save IrvingArmenta/45585cf58c1a8b4b3365bf8a61c4ff02 to your computer and use it in GitHub Desktop.
Hook for handling data fetch with loading and state, error handling and mocking data
import { useState, useEffect } from 'react';
const useFetchData = <T extends Record<string, unknown>>(
url: string,
options?: RequestInit,
mockData?: Promise<T>,
timeout = 600
) => {
const [data, setData] = useState<T | null>(null);
const [error, setError] = useState<Error | null>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
const abortController = new AbortController();
const { signal } = abortController;
const doFetch = async () => {
setLoading(true);
if (mockData) {
try {
await sleep(timeout);
const mockDataTyped = (await mockData) as T;
setData(mockDataTyped);
} catch (e) {
const err = e as Error;
if (!signal.aborted) {
setError(err);
}
} finally {
setLoading(false);
}
return;
}
try {
const res = await fetch(url, options);
const json = (await res.json()) as T;
if (!signal.aborted) {
setData(json);
}
} catch (e) {
const err = e as Error;
if (!signal.aborted) {
setError(err);
}
} finally {
if (!signal.aborted) {
setLoading(false);
}
}
};
doFetch();
return () => {
abortController.abort();
};
}, [options, url, mockData, timeout]);
return { data, error, loading };
};
export default useFetchData;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment