Title: fix(react-db): add getServerSnapshot to useSyncExternalStore for React 19 SSR#1534
Title: fix(react-db): add getServerSnapshot to useSyncExternalStore for React 19 SSR#15340Serenvale wants to merge 1 commit into
Conversation
…t 19 SSR 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.
📝 WalkthroughWalkthroughThe ChangesReact 19 SSR/hydration server snapshot stability
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/react-db/src/useLiveQuery.ts (1)
23-26: 💤 Low valueThe
as constassertion is unnecessary for reference stability.The comment states the constant is module-level for a "stable object reference," which is correct. However,
as constdoesn't provide reference stability—theconstkeyword already prevents reassignment of the binding. Theas constassertion only makes the object and its properties deeply readonly and narrows types to literals.While not harmful (and potentially beneficial for immutability), it may be confusing to attribute reference stability to
as constrather thanconst. Consider either removingas constor updating the comment to reflect that it provides readonly immutability rather than reference stability.Alternative without `as const`
-// 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 +// 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: number } = { + collection: null, + version: 0 +}This provides the same reference stability with a more explicit type annotation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/react-db/src/useLiveQuery.ts` around lines 23 - 26, The comment incorrectly attributes reference stability to the `as const` assertion on SERVER_SNAPSHOT in useLiveQuery.ts; remove the misleading `as const` (i.e., declare SERVER_SNAPSHOT = { collection: null, version: 0 } as the module-level const) or alternatively keep immutability but update the comment to say `as const` provides deep readonly typing rather than reference stability; locate SERVER_SNAPSHOT and either drop the `as const` assertion or adjust the comment text accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/react-db/src/useLiveQuery.ts`:
- Around line 23-26: The comment incorrectly attributes reference stability to
the `as const` assertion on SERVER_SNAPSHOT in useLiveQuery.ts; remove the
misleading `as const` (i.e., declare SERVER_SNAPSHOT = { collection: null,
version: 0 } as the module-level const) or alternatively keep immutability but
update the comment to say `as const` provides deep readonly typing rather than
reference stability; locate SERVER_SNAPSHOT and either drop the `as const`
assertion or adjust the comment text accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d7eb07b3-f892-4abf-a303-98c32e42ea21
📒 Files selected for processing (1)
packages/react-db/src/useLiveQuery.ts
React 19 requires
useSyncExternalStoreto receive a third argument (getServerSnapshot) when used in SSR/server component contexts (Next.js App Router). Without it, the app throws during hydration or enters an infinite render loop.The fix adds a module-level
SERVER_SNAPSHOTconstant passed as the third argument. It must be module-level — a new object created inside the hook on each render would fail React 19's stability check and cause an infinite loop.Reproduces with: Next.js 15/16 + React 19 +
@tanstack/react-dbin any SSR route that usesuseLiveQuery.🎯 Changes
SERVER_SNAPSHOTmodule-level constant inuseLiveQueryuseSyncExternalStoreto satisfy React 19's SSR requirements✅ Checklist
🚀 Release Impact
Patch release. No API changes. Fixes a crash/loop for all users on React 19 + SSR.