Skip to content

fix(react-router): render the pending document root only when its beforeLoad context exists - #8129

Closed
antur84 wants to merge 1 commit into
TanStack:mainfrom
antur84:fix/hydration-uncommitted-root-context
Closed

fix(react-router): render the pending document root only when its beforeLoad context exists#8129
antur84 wants to merge 1 commit into
TanStack:mainfrom
antur84:fix/hydration-uncommitted-root-context

Conversation

@antur84

@antur84 antur84 commented Aug 20, 2026

Copy link
Copy Markdown

Our root route gets its locale from beforeLoad context. About 95 times a day the root renders with that context missing and the app crashes.

We first blamed hydration, but production traces showed the real trigger: people navigating away from a 404 page. The 404 stops the router from reusing the root match, the rebuilt root has no context until beforeLoad finishes, and it gets rendered anyway.

One-click repro: https://github.com/antur84/tanstack-router-8128-repro — open any broken URL, click the 404 page's link.

The fix tracks whether beforeLoad has actually contributed to the current context, and only then lets a pending document root render its real component. Two regression tests: the hydration case and the 404-navigation case.

Fixes #8128.

…oreLoad context exists

The document-root pending exception keeps rendering the real component
because pending UI would remove <html> and hydrated matches retain their
prior data. An uncommitted hydrated root has no prior data: hydrate() only
merges the dehydrated beforeLoad context (b) for committed matches, so an
id-mismatched or stale root renders with every beforeLoad-provided context
key missing (TanStack#8115's production symptom, still present with TanStack#8116).

Track beforeLoad settlement on the client (__beforeLoadContext, mirroring
load-server) and via the dehydrated b for committed hydration, and gate the
document-root exception on it.
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 84d7dba6-9d25-4b95-b80e-34de3dd67418

📥 Commits

Reviewing files that changed from the base of the PR and between e9f63a6 and fba7a18.

📒 Files selected for processing (3)
  • packages/react-router/src/Match.tsx
  • packages/react-router/tests/issue-8115-hydration-context-window.test.tsx
  • packages/router-core/src/load-client.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The router now stores and restores beforeLoad context during hydration. MatchInner delays retained SSR root rendering when that context is not available. A regression test covers mismatched hydration data and asynchronous root loading.

Changes

Hydration context handling

Layer / File(s) Summary
Restore beforeLoad context
packages/router-core/src/load-client.ts
Client loading stores beforeLoad results on matches. Hydration restores serialized beforeLoad context, using an empty object when no context exists.
Gate SSR root rendering
packages/react-router/src/Match.tsx, packages/react-router/tests/issue-8115-hydration-context-window.test.tsx
MatchInner retains SSR output only when required beforeLoad context is available. The regression test verifies that the root receives locale before the index route renders.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to fba7a

This localized hydration fix is merge-ready after normal checks and review; no actionable merge-blocking risk remains.

Possibly related PRs

Suggested labels: package: react-router, package: router-core

Suggested reviewers: sheraff

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary change: gating pending document-root rendering on available beforeLoad context.
Linked Issues check ✅ Passed The changes track and restore beforeLoad context, gate unsafe root rendering, and add a regression test for issue #8128.
Out of Scope Changes check ✅ Passed All code and test changes directly support hydration context preservation and safe document-root rendering.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hydration renders the document root with beforeLoad-provided context stripped when the root fails commitment

2 participants