useOneTimeAsyncAction -> useAsyncMemo

This commit is contained in:
Michael Peters 2024-07-21 10:59:45 -07:00
parent 9514790f79
commit 462ba93f76

View File

@ -30,51 +30,55 @@ export function useIsMountedRef() {
}
/** returns a boolean state that will be true for a specified duration after the doShake function is called */
function useShake(ms: number): [shaking: boolean, doShake: () => void] {
function usePulse(ms: number): [shaking: boolean, doPulse: () => void] {
const isMounted = useIsMountedRef();
const [shaking, setShaking] = useState<boolean>(false);
const [pulsing, setPulsing] = useState<boolean>(false);
const doShake = useCallback(async () => {
const doPulse = useCallback(async () => {
if (!isMounted.current) return;
if (shaking) return;
setShaking(true);
if (pulsing) return;
setPulsing(true);
await sleep(ms);
if (!isMounted.current) return;
setShaking(false);
}, [isMounted, ms, shaking]);
setPulsing(false);
}, [isMounted, ms, pulsing]);
return [shaking, doShake];
return [pulsing, doPulse];
}
// runs an Async action one time (updates when deps changes)
export function useOneTimeAsyncAction<T, V>(
actionFunc: () => Promise<T>,
export function useAsyncMemo<T, V>(
calculateValue: () => Promise<T>,
deps: DependencyList,
initialValue: V,
): [value: T | V, error: unknown | null] {
): [value: T | V, pending: boolean, error: unknown | null] {
const isMounted = useIsMountedRef();
const [value, setValue] = useState<T | V>(initialValue);
const [pending, setPending] = useState<boolean>(false);
const [error, setError] = useState<unknown | null>(null);
useEffect(() => {
setPending(true);
(async () => {
try {
const value = await actionFunc();
const value = await calculateValue();
if (!isMounted.current) return;
setValue(value);
setPending(false);
setError(null);
} catch (e: unknown) {
console.error('unable to perform async action subscription', e);
if (!isMounted.current) return;
setPending(false);
setError(e);
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [actionFunc, ...deps]);
}, [calculateValue, ...deps]);
return [value, error];
return [value, pending, error];
}
/** creates a callable async function that will not double-trigger and gives a result, error message, and shaking boolean */
@ -88,7 +92,7 @@ export function useAsyncCallback<ResultType>(
const [result, setResult] = useState<ResultType | null>(null);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [shaking, doShake] = useShake(400);
const [shaking, doShake] = usePulse(400);
const [pending, setPending] = useState<boolean>(false);