import { useEffect, useRef, useState } from "react"; export default function useMemoSingleThreaded( fn: () => T | Promise, deps: any[], ): T { const [result, setResult] = useState(null); const updateInProgress = useRef(false); const updateRequired = useRef(false); useEffect(() => { const main = async () => { if (updateInProgress.current) { updateRequired.current = true; return; } updateInProgress.current = true; const result = fn(); if (isPromise(result)) { const resultValue = await result; setResult(resultValue); } else { setResult(result); } updateInProgress.current = false; if (updateRequired.current) { updateRequired.current = false; setTimeout(main, 0); } }; main(); }, deps); return result; } function isPromise(obj: T | Promise): obj is Promise { return obj && typeof (obj as any).then === "function"; }