diff --git a/.unipi/docs/fix/2026-06-04-favorites-display-loading-fix.md b/.unipi/docs/fix/2026-06-04-favorites-display-loading-fix.md new file mode 100644 index 0000000..ba7c05f --- /dev/null +++ b/.unipi/docs/fix/2026-06-04-favorites-display-loading-fix.md @@ -0,0 +1,41 @@ +--- +title: "Favorites Display Loading Blank Page — Quick Fix" +type: quick-fix +date: 2026-06-04 +--- + +# Favorites Display Loading Blank Page — Quick Fix + +## Bug + +When clicking the desktop header “我的收藏” button, the favorites page could briefly show the no-favorites empty state and then appear blank. The correct behavior is to show the user's favorited posts after loading. + +## Root Cause + +Two issues combined: + +1. The favorites page initialized with `loading=false` and `items=[]`. When the wallet was already logged in, React rendered the empty state once before the `useEffect` started the favorites request. +2. The desktop header favorites link had been changed to `reloadDocument` as a previous workaround. In the local Vite/dev-browser state this could force a full document reload and land in a broken empty document state instead of keeping the React app mounted. + +## Fix + +- Added an explicit `loaded` state to `src/pages/Favorites/index.tsx`. +- The favorites page now shows loading skeletons while logged-in favorites have not completed their first load, so the empty state only appears after a completed request returns zero items. +- Added a loading UI for `wallet.status === "loading"` so a persisted wallet token does not briefly show the logged-out prompt. +- Removed `reloadDocument` from the desktop header favorites link and kept client-side navigation with a top scroll reset. + +### Files Modified + +- `src/pages/Favorites/index.tsx` — tracks loaded state and gates empty-state rendering until favorites data has loaded. +- `src/layouts/PublicLayout.tsx` — removes hard document reload from the desktop header favorites link. + +## Verification + +- `npx tsc --noEmit` +- `npm run format:check` +- `npm test` +- Browser native: opened `http://192.168.1.187:5173/cn/browse`, clicked the desktop header “我的收藏”, and verified the resulting page URL is `/cn/favorites`, `document.getElementById("root")` exists, and `window.scrollY === 0`. + +## Notes + +No deploy was performed. diff --git a/src/layouts/PublicLayout.tsx b/src/layouts/PublicLayout.tsx index 3ff1ce1..9a0b2fe 100644 --- a/src/layouts/PublicLayout.tsx +++ b/src/layouts/PublicLayout.tsx @@ -698,7 +698,6 @@ export function PublicLayout() { /> window.scrollTo({ top: 0, left: 0 })} className={`hidden h-10 shrink-0 items-center justify-center gap-2 rounded-full border px-3 text-sm font-bold outline-none transition focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg md:inline-flex ${ na("favorites") diff --git a/src/pages/Favorites/index.tsx b/src/pages/Favorites/index.tsx index 5a9dcea..68088ea 100644 --- a/src/pages/Favorites/index.tsx +++ b/src/pages/Favorites/index.tsx @@ -137,6 +137,7 @@ export default function Favorites() { const [items, setItems] = useState([]); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); + const [loaded, setLoaded] = useState(false); const [error, setError] = useState(""); const [reloadKey, setReloadKey] = useState(0); const [showFilters, setShowFilters] = useState(false); @@ -151,10 +152,13 @@ export default function Favorites() { if (!wallet.token || wallet.status !== "loggedIn") { setItems([]); setTotal(0); + setLoading(false); + setLoaded(false); return; } let cancelled = false; setLoading(true); + setLoaded(false); setError(""); listFavorites(wallet.token, { sort, @@ -170,6 +174,7 @@ export default function Favorites() { setItems(resources); setTotal(data.total ?? resources.length); resources.forEach((resource) => markFavorite(resource.id, true)); + setLoaded(true); }) .catch((err) => { if (cancelled) return; @@ -179,6 +184,7 @@ export default function Favorites() { return; } setError(err instanceof Error ? err.message : t("loadFailed")); + setLoaded(true); }) .finally(() => { if (!cancelled) setLoading(false); @@ -200,6 +206,16 @@ export default function Favorites() { [t], ); + if (wallet.status === "loading") { + return ( + + {Array.from({ length: 4 }).map((_, index) => ( + + ))} + + ); + } + if (wallet.status !== "loggedIn") { return ( @@ -330,7 +346,7 @@ export default function Favorites() { ) : null} - {loading ? ( + {loading || !loaded ? (
{Array.from({ length: 4 }).map((_, index) => (