@mirawision/reactive-hooks
Version:
A comprehensive collection of 50+ React hooks for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Full TypeScript support with SSR safety.
66 lines (65 loc) • 2.09 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useAsync = useAsync;
const react_1 = require("react");
/**
* A hook that wraps an async function with state management.
* @param fn The async function to wrap
* @param deps Optional dependencies array that will trigger function reference update
* @returns AsyncState object containing run function, data, error, loading state, and reset function
*/
function useAsync(fn, deps = []) {
const [state, setState] = (0, react_1.useState)({
data: null,
error: null,
loading: false,
});
// Keep track of the latest call to handle race conditions
const callIdRef = (0, react_1.useRef)(0);
const fnRef = (0, react_1.useRef)(fn);
// Update function ref when function or deps change
(0, react_1.useEffect)(() => {
fnRef.current = fn;
}, [fn, ...deps]);
const run = (0, react_1.useCallback)(async (...args) => {
const callId = ++callIdRef.current;
setState(prev => ({ ...prev, loading: true, error: null }));
try {
const data = await fnRef.current(...args);
// Ignore result if a newer call has started
if (callId !== callIdRef.current)
return data;
setState(prev => ({
...prev,
data,
loading: false,
error: null,
}));
return data;
}
catch (error) {
// Ignore error if a newer call has started
if (callId !== callIdRef.current)
throw error;
setState(prev => ({
...prev,
error,
loading: false,
}));
throw error;
}
}, [] // Empty deps array since we handle updates via fnRef
);
const reset = (0, react_1.useCallback)(() => {
setState({
data: null,
error: null,
loading: false,
});
}, []);
return {
...state,
run,
reset,
};
}