@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
61 lines (57 loc) • 1.63 kB
JavaScript
"use client";
import { useMounted } from "../use-mounted/index.js";
import { useCallback, useEffect, useRef, useState } from "react";
//#region src/hooks/use-async/index.ts
/**
* `useAsync` is a custom hook that executes an asynchronous function and tracks its state.
*
* @see https://yamada-ui.com/docs/hooks/use-async
*/
function useAsync(func, deps = []) {
const [state, callback] = useAsyncFunc(func, deps, { loading: true });
useEffect(() => {
callback();
}, [callback]);
return state;
}
function useAsyncFunc(func, deps = [], initialState = { loading: false }) {
const lastCallId = useRef(0);
const mounted = useMounted();
const [state, setState] = useState(initialState);
return [state, useCallback((...args) => {
const callId = ++lastCallId.current;
if (!state.loading) setState((prevState) => ({
...prevState,
loading: true
}));
return func(...args).then((value) => {
if (mounted() && callId === lastCallId.current) setState({
loading: false,
value
});
return value;
}, (error) => {
if (mounted() && callId === lastCallId.current) setState({
error,
loading: false
});
return error;
});
}, deps)];
}
function useAsyncRetry(func, deps = []) {
const [attempt, setAttempt] = useState(0);
const state = useAsync(func, [...deps, attempt]);
const stateLoading = state.loading;
const retry = useCallback(() => {
if (stateLoading) return;
setAttempt((currentAttempt) => currentAttempt + 1);
}, [...deps, stateLoading]);
return {
...state,
retry
};
}
//#endregion
export { useAsync, useAsyncFunc, useAsyncRetry };
//# sourceMappingURL=index.js.map