@react-hookz/web
Version:
React hooks done right, for browser and SSR.
48 lines (47 loc) • 1.64 kB
JavaScript
import { useMemo, useRef } from 'react';
import { useAsync } from '..';
/**
* Like `useAsync`, but also provides `AbortSignal` as first function argument to async function.
*
* @param asyncFn Function that returns a promise.
* @param initialValue Value that will be set on initialisation, before the async function is
* executed.
*/
export function useAsyncAbortable(asyncFn, initialValue) {
const abortController = useRef();
const fn = async (...args) => {
// abort previous async
abortController.current?.abort();
// create new controller for ongoing async call
const ac = new AbortController();
abortController.current = ac;
// pass down abort signal and received arguments
return asyncFn(ac.signal, ...args).finally(() => {
// unset ref uf the call is last
if (abortController.current === ac) {
abortController.current = undefined;
}
});
};
const [state, asyncActions, asyncMeta] = useAsync(fn, initialValue);
return [
state,
useMemo(() => {
const actions = {
reset: () => {
actions.abort();
asyncActions.reset();
},
abort: () => {
abortController.current?.abort();
},
};
return {
...asyncActions,
...actions,
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []),
{ ...asyncMeta, abortController: abortController.current },
];
}