import { useEffect, useState } from "react"; import { api } from "../api"; import { AUTH_USER_CHANGED_EVENT, getAuthUserKey } from "../auth"; import { Company } from "../types"; import { useViewResource, ViewResourceError } from "./useViewResource"; let cachedCompanies: Company[] | null = null; let inflight: Promise | null = null; let cacheOwner = ""; function resetForOwner(owner: string) { if (cacheOwner === owner) return; cacheOwner = owner; cachedCompanies = null; inflight = null; } function cachedForCurrentOwner() { const owner = getAuthUserKey(); resetForOwner(owner); return cachedCompanies; } async function fetchCompanies(): Promise { const owner = getAuthUserKey(); resetForOwner(owner); if (cachedCompanies) return cachedCompanies; if (inflight) return inflight; const request = api .get('/companies') .then((r) => { if (cacheOwner === owner && getAuthUserKey() === owner) cachedCompanies = r.data; return r.data; }) .finally(() => { if (inflight === request) inflight = null; }); inflight = request; return inflight; } export function invalidateCompaniesCache() { cachedCompanies = null; inflight = null; } export function useCompanies(): { companies: Company[]; loading: boolean; refreshing: boolean; error: ViewResourceError | null; reload: () => Promise; } { const [cacheBust, setCacheBust] = useState(0); const resource = useViewResource(fetchCompanies, { initialData: cachedForCurrentOwner() ?? [], errorMessage: 'Unable to load companies right now.', deps: [cacheBust], }); useEffect(() => { if (!resource.error) { cachedCompanies = resource.data; } }, [resource.data, resource.error]); useEffect(() => { const reloadForAccount = () => { resetForOwner(getAuthUserKey()); setCacheBust((value) => value + 1); }; window.addEventListener(AUTH_USER_CHANGED_EVENT, reloadForAccount); return () => window.removeEventListener(AUTH_USER_CHANGED_EVENT, reloadForAccount); }, []); return { companies: resource.data, loading: resource.loading, refreshing: resource.refreshing, error: resource.error, reload: async () => { invalidateCompaniesCache(); setCacheBust((value) => value + 1); }, }; }