Skip to content

Instantly share code, notes, and snippets.

@lorenzorapetti
Created November 19, 2018 12:54
Show Gist options
  • Save lorenzorapetti/6617a4c4a7c2eb6315c763a66df6babf to your computer and use it in GitHub Desktop.
Save lorenzorapetti/6617a4c4a7c2eb6315c763a66df6babf to your computer and use it in GitHub Desktop.
React fetch hooks
import { useState, useEffect } from 'react';
export interface UseFetch<T> {
data: T | null;
isLoading: boolean;
error: ResponseError | Error | null;
retries: number;
retry: () => void;
}
export interface RequestOptions<T, E = T> extends RequestInit {
dataTransformer?: (data: T) => E;
json?: boolean;
}
export class ResponseError extends Error {
constructor(message: string, public statusCode: number, public statusText: string) {
super(message);
}
}
export default function useFetch<T = any, E = T>(
input: RequestInfo,
options: RequestOptions<T, E> = {},
): UseFetch<E> {
const [data, setData] = useState<E | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<ResponseError | Error | null>(null);
const [retries, setRetries] = useState(0);
const { dataTransformer, json = true, ...rest } = options;
useEffect(
() => {
setIsLoading(true);
fetch(input, rest)
.then(res => {
if (!res.ok) throw new ResponseError(res.statusText, res.status, res.statusText);
return json ? res.json() : res;
})
.then(res => (dataTransformer ? dataTransformer(res) : res))
.then(res => setData(res))
.catch(err => setError(err))
.finally(() => setIsLoading(false));
},
[retries],
);
function retry() {
setRetries(retries + 1);
}
return {
data,
isLoading,
error,
retries,
retry,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment