storytellurx-v1/app/hooks/use-async-memo.ts
2025-06-11 05:15:50 +02:00

46 lines
1.5 KiB
TypeScript

import { type DependencyList, useEffect, useState } from "react";
/**
* A custom hook that memoizes the result of an async function.
* It's a combination of useMemo and useEffect for asynchronous operations.
*
* @param asyncFactory A function that returns a Promise for the desired value.
* @param deps The dependency array. The async function is re-run when these change.
* @param initialValue An optional initial value to return while the promise is pending.
* @returns The resolved value of the promise, or the initialValue/undefined while pending.
*/
export function useAsyncMemo<T>(
asyncFactory: () => Promise<T>,
deps: DependencyList,
initialValue?: T,
): T | undefined {
const [value, setValue] = useState<T | undefined>(initialValue);
useEffect(() => {
let isCancelled = false;
asyncFactory()
.then((result) => {
if (!isCancelled) {
setValue(result);
}
})
.catch((error) => {
// It's good practice to handle potential errors
console.error("Error in useAsyncMemo:", error);
if (!isCancelled) {
// You might want to set an error state here
// For now, we'll just keep the old/initial value
}
});
// Cleanup function: If dependencies change before the promise resolves,
// this prevents setting state on an unmounted component or from a stale request.
return () => {
isCancelled = true;
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps);
return value;
}