-
-
Save bilalesi/72969e124d0e1c0ecc479565b5576347 to your computer and use it in GitHub Desktop.
A generic React fetch hook for API calls with caching, error handling, and refetch capability
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useCallback, useEffect, useState } from "react"; | |
| type FetchState<T> = { | |
| data: T | null; | |
| isLoading: boolean; | |
| error: Error | null; | |
| isCached: boolean; | |
| refetch: () => void; | |
| }; | |
| // A generic fetch hook for API calls with caching, error handling, and refetch capability | |
| function useFetch<T = unknown>( | |
| url: string, | |
| options?: RequestInit | |
| ): FetchState<T> { | |
| const [state, setState] = useState<FetchState<T>>({ | |
| data: null, | |
| isLoading: true, | |
| error: null, | |
| isCached: false, | |
| refetch: () => {}, | |
| }); | |
| const fetchData = useCallback( | |
| async (ignoreCache: boolean = false) => { | |
| setState((prevState) => ({ ...prevState, isLoading: true })); | |
| try { | |
| let data: T; | |
| let isCached = false; | |
| const cache = sessionStorage.getItem(url); | |
| if (cache && !ignoreCache) { | |
| data = JSON.parse(cache) as T; | |
| isCached = true; | |
| } else { | |
| const response = await fetch(url, options); | |
| if (!response.ok) { | |
| throw new Error(`Error: ${response.status}`); | |
| } | |
| data = await response.json(); | |
| sessionStorage.setItem(url, JSON.stringify(data)); | |
| } | |
| setState({ | |
| data, | |
| isLoading: false, | |
| error: null, | |
| isCached, | |
| refetch: () => fetchData(true), | |
| }); | |
| } catch (error) { | |
| setState((prevState) => ({ | |
| ...prevState, | |
| data: null, | |
| isLoading: false, | |
| error: error as Error, | |
| })); | |
| } | |
| }, | |
| [url, options] | |
| ); | |
| // Triggering the fetch operation when the URL or options change | |
| useEffect(() => { | |
| fetchData(); | |
| }, [fetchData]); | |
| return state; | |
| } | |
| export default useFetch; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment