From 9d1147a05246d1ad02f809f61a5508ed2a652af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 23 Oct 2026 19:25:30 +0200 Subject: [PATCH] fix(dashboard): fetch a snapshot restored from the offline copy on first mount The offline persister restores the last dashboard snapshot at boot and marks it invalidated so the first mount refetches it, but the snapshot cell read refetchOnMount: false and never did. A page reloaded right after a write, before the persister had flushed the newer snapshot, painted the pre-write dashboard until the two-minute poll; the weight just entered had no tile. A cell with live data still reads as it is on remount; a restored, invalidated one fetches. --- src/lib/queries/__tests__/use-dashboard-snapshot.test.tsx | 8 +++++++- src/lib/queries/use-dashboard-snapshot.ts | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/lib/queries/__tests__/use-dashboard-snapshot.test.tsx b/src/lib/queries/__tests__/use-dashboard-snapshot.test.tsx index 9205493a0..c19d91a69 100644 --- a/src/lib/queries/__tests__/use-dashboard-snapshot.test.tsx +++ b/src/lib/queries/__tests__/use-dashboard-snapshot.test.tsx @@ -83,7 +83,13 @@ describe("useDashboardSnapshot — auto-refresh on an open page", () => { useDashboardSnapshot(); const opts = lastOpts(); expect(opts.staleTime).toBe(60_000); - expect(opts.refetchOnMount).toBe(false); + const refetchOnMount = opts.refetchOnMount as (query: { + state: { isInvalidated: boolean }; + }) => boolean; + // A live cell is read as it is on remount ... + expect(refetchOnMount({ state: { isInvalidated: false } })).toBe(false); + // ... and one restored from the offline copy (invalidated) fetches. + expect(refetchOnMount({ state: { isInvalidated: true } })).toBe(true); }); it("always refetches on focus so freshness is not suppressed by staleTime", () => { diff --git a/src/lib/queries/use-dashboard-snapshot.ts b/src/lib/queries/use-dashboard-snapshot.ts index 9218ec6c3..280564b75 100644 --- a/src/lib/queries/use-dashboard-snapshot.ts +++ b/src/lib/queries/use-dashboard-snapshot.ts @@ -215,7 +215,13 @@ export function useDashboardSnapshot(enabled = true) { queryFn: makeSnapshotQueryFn(queryClient), enabled, staleTime: 60_000, - refetchOnMount: false, + // A remount of a cell that holds live data reads it as it is, but a cell + // restored from the offline copy (`restorePersistedQueryCache`) arrives + // invalidated and must fetch on its first mount. Plain `false` kept the + // restored copy on screen: a page reloaded right after a write, before + // the persister had flushed the newer snapshot, painted the pre-write + // dashboard until the two-minute poll. + refetchOnMount: (query) => query.state.isInvalidated, // Keep the snapshot and Today digest in lockstep after a background sync. // Both are out-of-band reads, so staleTime cannot signal that a worker // landed a new arrival while the browser was hidden.