import { DependencyList, useCallback, useState } from 'react'; import useRefMounted from './useRefMounted'; export type AsyncState = | { loading: boolean; error?: undefined; value?: undefined; } | { loading: false; error: Error; value?: undefined; } | { loading: false; error?: undefined; value: T; }; export type AsyncFn = [ AsyncState, (...args: Args | []) => Promise ]; export default function useAsyncFn( fn: (...args: Args | []) => Promise, deps: DependencyList = [], initialState: AsyncState = { loading: false } ): AsyncFn { const [state, set] = useState>(initialState); const mounted = useRefMounted(); const callback = useCallback((...args: Args | []) => { set({ loading: true }); return fn(...args).then( value => { if (mounted.current) { set({ value, loading: false }); } return value; }, error => { if (mounted.current) { set({ error, loading: false }); } return error; } ); }, deps); return [state, callback]; }