Skip to content

Instantly share code, notes, and snippets.

@Evanion
Created November 7, 2022 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Evanion/92efc1ae99b087e2c909a073747e82b7 to your computer and use it in GitHub Desktop.
Save Evanion/92efc1ae99b087e2c909a073747e82b7 to your computer and use it in GitHub Desktop.
useFetch hook for react.
import { DependencyList, useEffect, useReducer, useState } from "react";
interface State<T> {
data: T | null;
error: unknown | null;
loading: boolean;
loaded: boolean;
}
type Action<T> =
| { type: "FETCH_INIT" }
| { type: "FETCH_SUCCESS"; payload: T }
| { type: "FETCH_FAILURE"; payload: unknown };
const initialState = {
data: null,
loading: true,
loaded: false,
error: null,
};
export function useFetch<T>(input: RequestInfo, init?: RequestInit): State<T> {
const [state, dispatch] = useReducer<
(state: State<T>, action: Action<T>) => State<T>
>(reducer, initialState);
useEffect(() => {
const abortController = new AbortController();
const fetchData = async () => {
dispatch({ type: "FETCH_INIT" });
try {
const res = await fetch(input, {
...init,
signal: abortController.signal,
});
const data = await res.json();
dispatch({ type: "FETCH_SUCCESS", payload: data });
} catch (e: any) {
if (e.name === "AbortError") return;
dispatch({ type: "FETCH_FAILURE", payload: e });
}
};
fetchData();
return () => {
abortController.abort();
};
}, [input, init]);
return state;
}
function reducer<T>(state: State<T>, action: Action<T>): State<T> {
switch (action.type) {
case "FETCH_INIT":
return { ...state, loading: true };
case "FETCH_SUCCESS":
return { ...state, loading: false, loaded: true, data: action.payload };
case "FETCH_FAILURE":
return { ...state, loading: false, loaded: true, error: action.payload };
default:
return state;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment