mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
57 lines
1.4 KiB
TypeScript
57 lines
1.4 KiB
TypeScript
/* eslint-disable */
|
|
import { DependencyList, useCallback, useState, useRef } from 'react';
|
|
import useMountedState from './useMountedState';
|
|
|
|
export type AsyncState<T> =
|
|
| {
|
|
loading: boolean;
|
|
error?: undefined;
|
|
value?: undefined;
|
|
}
|
|
| {
|
|
loading: false;
|
|
error: Error;
|
|
value?: undefined;
|
|
}
|
|
| {
|
|
loading: false;
|
|
error?: undefined;
|
|
value: T;
|
|
};
|
|
|
|
export type AsyncFn<Result = any, Args extends any[] = any[]> = [
|
|
AsyncState<Result>,
|
|
(...args: Args | []) => Promise<Result>
|
|
];
|
|
|
|
export default function useAsyncFn<Result = any, Args extends any[] = any[]>(
|
|
fn: (...args: Args | []) => Promise<Result>,
|
|
deps: DependencyList = [],
|
|
initialState: AsyncState<Result> = { loading: false }
|
|
): AsyncFn<Result, Args> {
|
|
const lastCallId = useRef(0);
|
|
const [state, set] = useState<AsyncState<Result>>(initialState);
|
|
|
|
const isMounted = useMountedState();
|
|
|
|
const callback = useCallback((...args: Args | []) => {
|
|
const callId = ++lastCallId.current;
|
|
set({ loading: true });
|
|
|
|
return fn(...args).then(
|
|
value => {
|
|
isMounted() && callId === lastCallId.current && set({ value, loading: false });
|
|
|
|
return value;
|
|
},
|
|
error => {
|
|
isMounted() && callId === lastCallId.current && set({ error, loading: false });
|
|
|
|
return error;
|
|
}
|
|
);
|
|
}, deps);
|
|
|
|
return [state, callback];
|
|
}
|