Last active
September 3, 2021 11:46
-
-
Save FredrikAugust/9fde8b569477d9e5b3de3a4d1f724e99 to your computer and use it in GitHub Desktop.
useFetch with cancellation token
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 { useEffect, useState } from 'react'; | |
export type UseFetchReturnType<T> = { | |
loading: boolean; | |
data?: T; | |
error?: Error; | |
}; | |
type FetchParameters = Parameters<typeof fetch>; | |
/** | |
* Helper function to fetch resources from an API. Uses AbortControllers to ensure that fetch | |
* calls are aborted when the component which invoked the call is unmounted. This avoids | |
* "performing operations on an unmounted component" errors due to fetch calls. | |
* | |
* @param url RequestInfo or string url to fetch | |
* @param options Options passed to fetch. Signal can be overridden by specifying it here. | |
* @param dependencies Optional list of dependencies. When these change, the request will be re-retrieved. | |
*/ | |
export default function useFetch<T>( | |
url: FetchParameters[0], | |
options: FetchParameters[1] = {}, | |
dependencies: Array<unknown> = [], | |
): UseFetchReturnType<T> { | |
const [loading, setLoading] = useState(true); | |
const [data, setData] = useState<T>(); | |
const [error, setError] = useState<Error>(); | |
const abortController = new AbortController(); | |
useEffect(() => { | |
(async () => { | |
try { | |
const response = await fetch(url, { signal: abortController.signal, ...options }); | |
const data = await response.json(); | |
setData(data); | |
setLoading(false); | |
} catch (e) { | |
if (e instanceof DOMException) { | |
// aborted fetch, don't update UI | |
// this will cause update after unmount exceptions | |
return; | |
} | |
setLoading(false); | |
setError(e); | |
} | |
})(); | |
return () => abortController.abort(); | |
}, dependencies); | |
return { loading, data, error }; | |
} |
Slightly more complex example
const { loading, data } = useFetch<FishDetails>(
`/fish/${fishID}`,
{ method: 'POST', body: JSON.stringify({ fishName: 'John the Fish' }) },
[props.fishes],
);
By default it runs a GET request once per mount
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example usage