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
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:
@@ -47,12 +47,18 @@
|
||||
// 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
|
||||
// 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 & {
|
||||
allLoaded: number;
|
||||
allSort: AllSort;
|
||||
allExhausted: boolean;
|
||||
};
|
||||
let pendingPagination: { count: number; sort: AllSort; exhausted: boolean } | null = null;
|
||||
|
||||
export const snapshot: Snapshot<HomeSnapshot> = {
|
||||
capture: () => ({
|
||||
@@ -64,12 +70,8 @@
|
||||
restore: (s) => {
|
||||
store.restoreSnapshot(s);
|
||||
if (s.allLoaded > 0) {
|
||||
pendingPagination = {
|
||||
count: s.allLoaded,
|
||||
sort: s.allSort,
|
||||
exhausted: s.allExhausted
|
||||
};
|
||||
allSort = s.allSort;
|
||||
void rehydrateAll(s.allSort, s.allLoaded, s.allExhausted);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -161,20 +163,15 @@
|
||||
if (urlQ) store.query = urlQ;
|
||||
void loadRecent();
|
||||
void searchFilterStore.load();
|
||||
if (pendingPagination) {
|
||||
// Back-navigation: restore the full loaded depth in one shot so
|
||||
// the document is tall enough for scroll-restore to land. Sort
|
||||
// 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;
|
||||
}
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user