Skip to content

Instantly share code, notes, and snippets.

@latobibor
Last active June 28, 2024 00:25
Show Gist options
  • Save latobibor/a3b74b4697b593c85352cf80ce4239e5 to your computer and use it in GitHub Desktop.
Save latobibor/a3b74b4697b593c85352cf80ce4239e5 to your computer and use it in GitHub Desktop.
useAbortableFetch
import { useRef } from 'react';
// wanna send a ton of requests but only needing the last one?
// note: on the backend even aborted requests are going to use resources
export function useAbortableFetch() {
const controllerRef = useRef<AbortController | null>(null);
async function fetchThatAbortsPreviousCall(
input: string | URL | Request,
options?: RequestInit,
) {
try {
if (controllerRef.current) {
console.log('Aborting previous call...');
controllerRef.current.abort();
controllerRef.current = null;
}
if (controllerRef.current === null) {
controllerRef.current = new AbortController();
}
const result = await fetch(input, {
...options,
signal: controllerRef.current.signal,
});
if (!result.ok) {
// this is not proper error handling, just for debug uses
console.error(result);
}
// for sake of simplicity we unbox the json value, but you might encounter other result types
const unboxedValue = await result.json();
controllerRef.current = null;
return unboxedValue;
} catch (error) {
// In case of the AbortError it just returns null; this can be customized
if (error instanceof DOMException && error.name === 'AbortError') {
return null;
}
throw error;
}
}
return { fetchThatAbortsPreviousCall };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment