Skip to content

Instantly share code, notes, and snippets.

@philipyoungg
Last active July 19, 2022 22:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save philipyoungg/a76c6a3467b024cfed29d3c62b2d7d53 to your computer and use it in GitHub Desktop.
Save philipyoungg/a76c6a3467b024cfed29d3c62b2d7d53 to your computer and use it in GitHub Desktop.
Typescript useFetch
// mocks
const mockUser = {}
const mockGoals = []
// endpoint
enum ApiEndpoint {
FetchAllGoals = '/goals',
CurrentUser = '/user',
}
// fetcher
const fetchUserGoals = (): Promise<Goal[]> =>
new Promise((res) => {
setTimeout(() => res(mockGoals), 250);
});
const currentUser = (): Promise<User> =>
new Promise((res) => {
setTimeout(() => res(mockUser), 250);
});
// useFetch
const endpointToPromiseMap = {
[ApiEndpoint.FetchAllGoals]: fetchUserGoals,
[ApiEndpoint.CurrentUser]: currentUser,
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const useFetch = <V>(endpoint: ApiEndpoint, args?: V) => {
const prms = endpointToPromiseMap[endpoint];
return _useFetch(prms, args);
};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const _useFetch = <T, L>(prms: (arg0?: L) => Promise<T>, args?: L) => {
const isMounted = useRef(true);
const [data, setData] = useState<T | null>(null);
const [errorMessage, setErrorMessage] = useState<string>('');
const [status, setStatus] = useState<FetchStatus>(FetchStatus.Loading);
useEffect(() => {
const fn = async () => {
try {
setStatus(FetchStatus.Loading);
const payload = await prms(args);
if (isMounted) {
setData(payload);
setStatus(FetchStatus.Success);
}
} catch (err) {
if (isMounted) {
setErrorMessage(err.message);
setStatus(FetchStatus.Failed);
}
}
};
fn();
return () => {
isMounted.current = false;
};
}, []);
return {
status,
errorMessage,
data,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment