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 */ /** 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 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 (!isMounted.current) return;
if (shaking) return; if (pulsing) return;
setShaking(true); setPulsing(true);
await sleep(ms); await sleep(ms);
if (!isMounted.current) return; if (!isMounted.current) return;
setShaking(false); setPulsing(false);
}, [isMounted, ms, shaking]); }, [isMounted, ms, pulsing]);
return [shaking, doShake]; return [pulsing, doPulse];
} }
// runs an Async action one time (updates when deps changes) // runs an Async action one time (updates when deps changes)
export function useOneTimeAsyncAction<T, V>( export function useAsyncMemo<T, V>(
actionFunc: () => Promise<T>, calculateValue: () => Promise<T>,
deps: DependencyList, deps: DependencyList,
initialValue: V, initialValue: V,
): [value: T | V, error: unknown | null] { ): [value: T | V, pending: boolean, error: unknown | null] {
const isMounted = useIsMountedRef(); const isMounted = useIsMountedRef();
const [value, setValue] = useState<T | V>(initialValue); const [value, setValue] = useState<T | V>(initialValue);
const [pending, setPending] = useState<boolean>(false);
const [error, setError] = useState<unknown | null>(null); const [error, setError] = useState<unknown | null>(null);
useEffect(() => { useEffect(() => {
setPending(true);
(async () => { (async () => {
try { try {
const value = await actionFunc(); const value = await calculateValue();
if (!isMounted.current) return; if (!isMounted.current) return;
setValue(value); setValue(value);
setPending(false);
setError(null); setError(null);
} catch (e: unknown) { } catch (e: unknown) {
console.error('unable to perform async action subscription', e); console.error('unable to perform async action subscription', e);
if (!isMounted.current) return; if (!isMounted.current) return;
setPending(false);
setError(e); setError(e);
} }
})(); })();
// eslint-disable-next-line react-hooks/exhaustive-deps // 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 */ /** 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 [result, setResult] = useState<ResultType | null>(null);
const [errorMessage, setErrorMessage] = useState<string | 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); const [pending, setPending] = useState<boolean>(false);