Add stale cache for public data
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { getJSON, itemsOrEmpty, type Category } from "../../api";
|
||||
import { getJSON, itemsOrEmpty, readJSONCache, type Category } from "../../api";
|
||||
import { CategoryIcon } from "../../components/CategoryIcon";
|
||||
import { FigmaBanner } from "../../components/FigmaBanner";
|
||||
import {
|
||||
@@ -61,41 +61,80 @@ export function Home() {
|
||||
const [recScroll, setRecScroll] = useState({ ratio: 1, progress: 0 });
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const langParam = encodeURIComponent(langQuery(lang));
|
||||
const languageParam = encodeURIComponent(sourceLanguageQuery(lang));
|
||||
const catQ = `?lang=${langParam}`;
|
||||
const postQ = `?lang=${langParam}&language=${languageParam}`;
|
||||
const categoriesUrl = `/api/categories${catQ}`;
|
||||
const recommendedUrl = `/api/posts/recommended${postQ}&limit=12`;
|
||||
const latestUrl = `/api/posts${postQ}&sort=latest&limit=12`;
|
||||
const popularUrl = `/api/posts${postQ}&sort=popular&limit=5`;
|
||||
|
||||
const applyHomeData = (
|
||||
c: Category[],
|
||||
r: { items: Post[] },
|
||||
l: { items: Post[] },
|
||||
p: { items: Post[] },
|
||||
) => {
|
||||
const categoryItems = itemsOrEmpty(c);
|
||||
setCats(categoryItems);
|
||||
setRec(
|
||||
itemsOrEmpty(r.items).map((post) =>
|
||||
postToResource(post, lang, categoryItems),
|
||||
),
|
||||
);
|
||||
const latestItems = itemsOrEmpty(l.items);
|
||||
setLatestPosts(latestItems);
|
||||
setLatest(
|
||||
latestItems.map((post) => postToResource(post, lang, categoryItems)),
|
||||
);
|
||||
const popularItems = itemsOrEmpty<Post>(p.items);
|
||||
setPopularPosts(popularItems);
|
||||
setPopular(
|
||||
popularItems.map((post) => postToResource(post, lang, categoryItems)),
|
||||
);
|
||||
};
|
||||
|
||||
setErr(null);
|
||||
const cachedCategories = readJSONCache<Category[]>(categoriesUrl);
|
||||
const cachedRecommended = readJSONCache<{ items: Post[] }>(recommendedUrl);
|
||||
const cachedLatest = readJSONCache<{ items: Post[] }>(latestUrl);
|
||||
const cachedPopular = readJSONCache<{ items: Post[] }>(popularUrl);
|
||||
const showedCached = !!(
|
||||
cachedCategories &&
|
||||
cachedRecommended &&
|
||||
cachedLatest
|
||||
);
|
||||
|
||||
if (showedCached) {
|
||||
applyHomeData(
|
||||
cachedCategories,
|
||||
cachedRecommended,
|
||||
cachedLatest,
|
||||
cachedPopular ?? { items: [] },
|
||||
);
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
getJSON<Category[]>(`/api/categories${catQ}`),
|
||||
getJSON<{ items: Post[] }>(`/api/posts/recommended${postQ}&limit=12`),
|
||||
getJSON<{ items: Post[] }>(`/api/posts${postQ}&sort=latest&limit=12`),
|
||||
getJSON<{ items: Post[] }>(
|
||||
`/api/posts${postQ}&sort=popular&limit=5`,
|
||||
).catch((): { items: Post[] } => ({ items: [] })),
|
||||
getJSON<Category[]>(categoriesUrl),
|
||||
getJSON<{ items: Post[] }>(recommendedUrl),
|
||||
getJSON<{ items: Post[] }>(latestUrl),
|
||||
getJSON<{ items: Post[] }>(popularUrl).catch(
|
||||
(): { items: Post[] } => cachedPopular ?? { items: [] },
|
||||
),
|
||||
])
|
||||
.then(([c, r, l, p]) => {
|
||||
setCats(itemsOrEmpty(c));
|
||||
setRec(
|
||||
itemsOrEmpty(r.items).map((post) =>
|
||||
postToResource(post, lang, itemsOrEmpty(c)),
|
||||
),
|
||||
);
|
||||
const latestItems = itemsOrEmpty(l.items);
|
||||
setLatestPosts(latestItems);
|
||||
setLatest(
|
||||
latestItems.map((post) =>
|
||||
postToResource(post, lang, itemsOrEmpty(c)),
|
||||
),
|
||||
);
|
||||
const popularItems = itemsOrEmpty<Post>(p.items);
|
||||
setPopularPosts(popularItems);
|
||||
setPopular(
|
||||
popularItems.map((post) =>
|
||||
postToResource(post, lang, itemsOrEmpty(c)),
|
||||
),
|
||||
);
|
||||
if (cancelled) return;
|
||||
applyHomeData(c, r, l, p);
|
||||
})
|
||||
.catch((e) => setErr(String(e)));
|
||||
.catch((e) => {
|
||||
if (!cancelled && !showedCached) setErr(String(e));
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [lang]);
|
||||
|
||||
const iconKeyForResource = (r: PostBackedResource) =>
|
||||
|
||||
Reference in New Issue
Block a user