fix(home): rehydrate-Trigger aus snapshot.restore, nicht ueber onMount
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m16s

Live-Test mit Fetch-Hook auf kochwas-dev hat bewiesen: bei tiefem
Endless-Scroll (60 Items) und Back-Nav fired rehydrateAll nie. Der
Logger zeigte nur limit=10&offset=0 plus IO-Trigger (10&offset=10).

Root Cause: SvelteKit ruft snapshot.restore *nach* onMount (post-mount
tick). Der vorherige Code parkte die Tiefe in pendingPagination und
liess onMount entscheiden — onMount lief aber zuerst, sah null, fiel
auf loadAllMore() zurueck. Restore setzte danach pendingPagination,
aber niemand las es mehr.

Fix: rehydrateAll direkt aus restore aufrufen (fire-and-forget).
onMount macht unkonditional loadAllMore() fuer den Fresh-Mount-Fall;
beide Pfade greifen ueber das allLoading-Flag bzw. ueber den
allRecipes-Overwrite (rehydrateAll's groesseres Result gewinnt
spaeter). Wasted-Fetch im Worst-Case: 10 Items (~2 KB) — vertretbar.

pendingPagination raus, onMount-Conditional vereinfacht.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-22 09:59:11 +02:00
parent 1d7731edbb
commit 005c3ea7b5

View File

@@ -47,12 +47,18 @@
// recipes via infinite scroll") so on back-nav we can re-hydrate the // recipes via infinite scroll") so on back-nav we can re-hydrate the
// full list in one fetch — otherwise the document is too short and // full list in one fetch — otherwise the document is too short and
// scroll-restore can't reach the saved Y position. // scroll-restore can't reach the saved Y position.
//
// SvelteKit calls snapshot.restore AFTER onMount (post-mount tick),
// so a flag-based handoff to onMount won't fire — we trigger
// rehydrateAll directly from restore. onMount still calls
// loadAllMore() for the fresh-mount case; if restore lands first,
// allLoading guards the duplicate fetch, otherwise rehydrateAll's
// larger result simply overwrites loadAllMore's initial 10 items.
type HomeSnapshot = SearchSnapshot & { type HomeSnapshot = SearchSnapshot & {
allLoaded: number; allLoaded: number;
allSort: AllSort; allSort: AllSort;
allExhausted: boolean; allExhausted: boolean;
}; };
let pendingPagination: { count: number; sort: AllSort; exhausted: boolean } | null = null;
export const snapshot: Snapshot<HomeSnapshot> = { export const snapshot: Snapshot<HomeSnapshot> = {
capture: () => ({ capture: () => ({
@@ -64,12 +70,8 @@
restore: (s) => { restore: (s) => {
store.restoreSnapshot(s); store.restoreSnapshot(s);
if (s.allLoaded > 0) { if (s.allLoaded > 0) {
pendingPagination = {
count: s.allLoaded,
sort: s.allSort,
exhausted: s.allExhausted
};
allSort = s.allSort; allSort = s.allSort;
void rehydrateAll(s.allSort, s.allLoaded, s.allExhausted);
} }
} }
}; };
@@ -161,20 +163,15 @@
if (urlQ) store.query = urlQ; if (urlQ) store.query = urlQ;
void loadRecent(); void loadRecent();
void searchFilterStore.load(); void searchFilterStore.load();
if (pendingPagination) { const saved = localStorage.getItem('kochwas.allSort');
// Back-navigation: restore the full loaded depth in one shot so if (saved && ['name', 'rating', 'cooked', 'created'].includes(saved)) {
// the document is tall enough for scroll-restore to land. Sort allSort = saved as AllSort;
// already came from the snapshot — don't read localStorage here.
const p = pendingPagination;
pendingPagination = null;
void rehydrateAll(p.sort, p.count, p.exhausted);
} else {
const saved = localStorage.getItem('kochwas.allSort');
if (saved && ['name', 'rating', 'cooked', 'created'].includes(saved)) {
allSort = saved as AllSort;
}
void loadAllMore();
} }
// Fresh-mount: kick off the initial 10. On back-nav, snapshot.restore
// also fires rehydrateAll(60); if it lands first, allLoading guards
// this; if loadAllMore lands first, rehydrateAll's larger result
// simply overwrites allRecipes once it resolves.
void loadAllMore();
}); });
// IntersectionObserver an den Sentinel hängen — wenn sichtbar, nachladen. // IntersectionObserver an den Sentinel hängen — wenn sichtbar, nachladen.