From ccfaa53501317286e9041783f7b9d8c7920559f3 Mon Sep 17 00:00:00 2001 From: 0serenvale Date: Mon, 18 May 2026 08:02:13 +0100 Subject: [PATCH] fix(react-db): add getServerSnapshot to useSyncExternalStore for React 19 SSR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit React 19 requires useSyncExternalStore to receive a third argument (getServerSnapshot) when used in SSR/server component contexts. Without it, Next.js App Router throws during hydration or enters an infinite render loop. The fix adds a module-level SERVER_SNAPSHOT constant and passes it as the third argument. It must be module-level — a new object created inside the hook on each call would fail React 19's stability check and loop. Fixes SSR usage in Next.js 15+ with React 19. --- packages/react-db/src/useLiveQuery.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/react-db/src/useLiveQuery.ts b/packages/react-db/src/useLiveQuery.ts index 331ff3a279..0e0777848e 100644 --- a/packages/react-db/src/useLiveQuery.ts +++ b/packages/react-db/src/useLiveQuery.ts @@ -20,6 +20,11 @@ import type { const DEFAULT_GC_TIME_MS = 1 // Live queries created by useLiveQuery are cleaned up immediately (0 disables GC) +// Module-level constant so React 19 receives a stable object reference for the +// server snapshot. Creating this inside the hook would produce a new reference +// on every render, causing an infinite loop during SSR/hydration. +const SERVER_SNAPSHOT = { collection: null, version: 0 } as const + export type UseLiveQueryStatus = CollectionStatus | `disabled` /** @@ -483,6 +488,7 @@ export function useLiveQuery( const snapshot = useSyncExternalStore( subscribeRef.current, getSnapshotRef.current, + () => SERVER_SNAPSHOT, ) // Track last snapshot (from useSyncExternalStore) and the returned value separately