Spaces:
Sleeping
Sleeping
File size: 1,552 Bytes
1c8e50c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
import { useCallback, useEffect, useRef, useState } from 'react';
const noop = () => {};
/**
* Lightweight helper for managing async side-effects with loading and error states.
*/
export const useAsync = (asyncFunction, options = {}) => {
const { immediate = false, onSuccess = noop, onError = noop, resetOnExecute = true } = options;
const [status, setStatus] = useState('idle');
const [value, setValue] = useState(null);
const [error, setError] = useState(null);
const mountedRef = useRef(true);
useEffect(() => {
return () => {
mountedRef.current = false;
};
}, []);
const execute = useCallback(
async (...args) => {
setStatus('pending');
if (resetOnExecute) {
setValue(null);
setError(null);
}
try {
const result = await asyncFunction(...args);
if (!mountedRef.current) return result;
setValue(result);
setStatus('success');
onSuccess(result);
return result;
} catch (err) {
if (!mountedRef.current) throw err;
setError(err);
setStatus('error');
onError(err);
throw err;
}
},
[asyncFunction, onError, onSuccess, resetOnExecute]
);
useEffect(() => {
if (immediate) {
execute();
}
}, [execute, immediate]);
return {
execute,
status,
value,
error,
isIdle: status === 'idle',
isLoading: status === 'pending',
isSuccess: status === 'success',
isError: status === 'error',
};
};
export default useAsync;
|