import { useEffect, useState } from "react"; import { useClient } from "../AppConfig/AppConfig.tsx"; import { type Failure, Pending, type Success } from "../async-op.ts"; import type { CurrentUser, FailurePayload } from "../types.ts"; export function useFetchCurrentUser(options?: { /** * Optionally disable immediate fetch action. * * @default true */ performFetch?: boolean; /** * Fetch new data every time the window is focused. * * Note that `performFetch` has to be enabled for this option to have an * effect — we are not revalidating when there is no fetch to do! * * @default false */ revalidateOnFocus?: boolean; }) { const { performFetch = true, revalidateOnFocus = false } = options ?? {}; const client = useClient(); const [latestAttemptTs, setLatestAttemptTs] = useState(Date.now()); const [result, setResult] = useState< Success | Failure | Pending >(new Pending()); // We are intentionally not using SWR in this case, as we don't want to deal // with caching or any of that business. useEffect(() => { if (performFetch) { const fetchUserAndStoreResult = async () => { const result = await client.getCurrentUser(); setResult(result); }; // Invoke the fetch action fetchUserAndStoreResult(); if (revalidateOnFocus) { const controller = new AbortController(); window.addEventListener("focus", fetchUserAndStoreResult, controller); return () => { controller.abort(); }; } } }, [client, latestAttemptTs, performFetch]); return { result, latestAttemptTs, reload: () => { setResult(new Pending()); setLatestAttemptTs(Date.now()); }, }; }