Skip to content

Instantly share code, notes, and snippets.

@VitorLuizC
Last active July 21, 2020 15:47
Show Gist options
  • Save VitorLuizC/8f0fd51b03b822ba1fdd7c91fc758fa4 to your computer and use it in GitHub Desktop.
Save VitorLuizC/8f0fd51b03b822ba1fdd7c91fc758fa4 to your computer and use it in GitHub Desktop.
import { useCallback, useMemo, useState } from 'react';
type ValueOrPromiseValue<Value> = Value extends Promise<infer PromiseValue>
? PromiseValue
: Value;
const useLoading = () => {
const [ticks, setTicks] = useState(0);
const withLoading = useCallback(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
<F extends (this: any, ...args: any[]) => any>(fn: F) => {
const loadable = function loadable(
this: ThisParameterType<F>,
...args: Parameters<F>
): Promise<ValueOrPromiseValue<ReturnType<F>>> {
setTicks(ticks => ticks + 1);
return new Promise<ValueOrPromiseValue<ReturnType<F>>>(
(resolve, reject) => {
try {
resolve(fn.apply(this, args));
} catch (error) {
reject(error);
}
}
).finally(() => setTicks(ticks => ticks - 1));
};
loadable.name = `withLoading(${fn.name ?? 'Anonymous Function'})`;
return loadable;
},
[]
);
const loading = useMemo(() => ticks > 0, [ticks]);
return {
loading,
withLoading
};
};
export default useLoading;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment