fix(router-plugin): don't patch foreign routers on first route-module import - #7937
Open
FrancoKaddour wants to merge 1 commit into
Open
fix(router-plugin): don't patch foreign routers on first route-module import#7937FrancoKaddour wants to merge 1 commit into
FrancoKaddour wants to merge 1 commit into
Conversation
… import Since 1.168.17 (837897f, TanStack#7560) the injected Vite HMR preamble eagerly calls handleRouteUpdate during the initial evaluation of every route module whenever window.__TSR_ROUTER__ already owns a route with the same id but a different object identity. With multiple routers in one window (module federation host/remote), route ids like __root__ collide between apps and the last-created router wins the global, so the remote's route modules patch the host's router on first import and get the host's tree state written back into their own Route exports — mixing components across the two React copies and triggering "Invalid hook call". hot.data persists across re-evaluations of a module but starts empty on first import, which is exactly the missing discriminator: the eager patch (only needed for the TanStack#4303 aliased-import re-evaluation case) is now gated behind a tsr-route-initialized flag in hot.data, restoring pre-1.168.17 behavior for first imports while keeping TanStack#4303 fixed. Closes TanStack#7921
Contributor
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (14)
📝 WalkthroughWalkthroughChangesHMR route initialization
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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 |
FrancoKaddour
marked this pull request as ready for review
August 3, 2026 12:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #7921
Problem
Since
@tanstack/router-plugin@1.168.17(837897f, #7560), the injected Vite HMR preamble eagerly callshandleRouteUpdateduring the initial evaluation of every route module wheneverwindow.__TSR_ROUTER__already owns a route with the same id but a different object identity.That heuristic assumes "same id + different identity ⇒ re-imported copy of this file". With multiple routers in one window (module federation host/remote, microfrontends), route ids like
__root__and/collide between apps, andwindow.__TSR_ROUTER__points at whichever router was created last. The remote's route modules then patch the host's router: the host's route options are overwritten,preserveComponentIdentitygrafts the host's components onto the remote's route options, andsyncHotRouteExportrewrites the remote'sRouteexport (parentRoute,_id,_path, …) with the host's tree state. Since each app ships its own React copy in dev, rendering the remote's router executes components bound to the host's React → "Invalid hook call". Creating the host router is enough to trigger it — no rendering needed.Fix
Vite's
hot.datapersists across re-evaluations of a module but starts empty on first import — exactly the missing discriminator. The eager patch (only needed for the #4303 aliased-import re-evaluation case) is now gated behind atsr-route-initializedflag inhot.data, restoring the pre-1.168.17 behavior for first imports while keeping the #4303 fix intact.Note: the
hot.acceptpath has always resolvedwindow.__TSR_ROUTER__(pre-1.168.17), so editing a route file while a foreign router was created last can still target the wrong router. That's a pre-existing, edit-time-only limitation; properly scoping the global to a per-router registry is left as a follow-up if maintainers want it.Summary by CodeRabbit
Bug Fixes
Tests