Skip to content

Instantly share code, notes, and snippets.

@krnlde
Last active October 7, 2021 09:25
Show Gist options
  • Save krnlde/f1a8f3882baceb59ca7cc82b34e77fbd to your computer and use it in GitHub Desktop.
Save krnlde/f1a8f3882baceb59ca7cc82b34e77fbd to your computer and use it in GitHub Desktop.
react hook for abortable async results
export function useAbortableAsyncResult<T extends any = any>(
fn: (signal: AbortSignal, clearData: () => void) => Promise<T>,
dependencies: DependencyList = []
) {
const isMounted = React.useRef(false);
const abortController = React.useRef<AbortController>();
const [isInitialized, setIsInitialized] = React.useState(false);
const [data, setData] = React.useState<T>();
const [error, setError] = React.useState<Error>();
const [isLoading, setIsLoading] = React.useState(false);
React.useEffect(() => {
isMounted.current = true;
return () => isMounted.current = false;
}, []);
const clearData = () => {
if (isMounted.current) setData(null);
};
const reload = React.useCallback(async () => {
if (abortController.current) {
/*
ATTENTION this will through asynchrounosly (in the next tick)
This is why I set isLoading explicitly here
*/
abortController.current.abort();
if (isMounted.current) setIsLoading(false);
}
abortController.current = new AbortController();
try {
setError(null);
setIsLoading(true);
const response = await fn(abortController.current.signal, clearData);
if (isMounted.current) setData(response);
if (isMounted.current) setIsLoading(false);
if (isMounted.current) setIsInitialized(true);
} catch (e) {
if (e instanceof DOMException && e.name === 'AbortError') return;
if (isMounted.current) setError(e);
if (isMounted.current) setIsLoading(false);
if (isMounted.current) setIsInitialized(true);
clearData();
console.warn(e);
}
}, dependencies);
// Load on componentDidMount, and whenever the reload-method changes
React.useEffect(() => void reload(), [reload]);
return { isInitialized, isLoading, reload, error, data, abort: abortController.current?.abort };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment