Files
wikideck/src/useEnrichment.ts
T
2026-10-19 16:47:27 -04:00

29 lines
1.3 KiB
TypeScript

import { useEffect, useState } from 'react';
import type { PageEnrichment } from '../shared/enrichment.ts';
// One request per article shared by hero, collection and detail views. No wallet data is sent.
const cache = new Map<number, { expires: number; job: Promise<PageEnrichment> }>();
function load(pageId: number): Promise<PageEnrichment> {
const existing=cache.get(pageId);
if(existing && existing.expires>Date.now())return existing.job;
const job=(async()=>{
const response=await fetch(`/api/wikipedia/${pageId}`,{signal:AbortSignal.timeout(15000),cache:'no-store'});
if(!response.ok)throw new Error('Live Wikipedia data unavailable');
return await response.json() as PageEnrichment;
})();
cache.set(pageId,{expires:Date.now()+5*60*1000,job});
if(cache.size>128)cache.delete(cache.keys().next().value!);
return job;
}
export function useEnrichment(pageId: number) {
const [data,setData]=useState<PageEnrichment>();
const [error,setError]=useState(false);
const [attempt,setAttempt]=useState(0);
useEffect(()=>{
let active=true;setData(undefined);setError(false);
load(pageId).then(value=>{if(active)setData(value);},()=>{if(active)setError(true);});
return()=>{active=false;};
},[pageId,attempt]);
return {data,error,retry:()=>{cache.delete(pageId);setAttempt(n=>n+1);}};
}