Which project does this relate to?
Router
Describe the bug
Since @tanstack/react-router@1.170.19 / @tanstack/router-core@1.171.16
(the match-loading rewrite in #7805), a navigation that only changes search
params or a path param on an already-mounted route swaps the page to the
route's pendingComponent while a parent layout's async beforeLoad re-runs.
On 1.170.18 the mounted UI stayed on screen during such navigations; the
pending component only appeared when there was nothing rendered yet (initial
load). With defaultPendingMs: 0 (pending immediately on cold start) and
defaultPendingMinMs: 250, our app now flashes a full-page spinner for at
least 250 ms on every in-app tab switch and every sibling-route switch,
because the layout's auth-guard beforeLoad does a network round trip.
Shape that reproduces it: a pathless layout route with an async beforeLoad,
a child route /projects/$projectId with validateSearch, router options
defaultPendingMs: 0, defaultPendingMinMs: 250.
Complete minimal reproducer
https://github.com/salty-flower/tsr-pending-navigation-repro
Steps to Reproduce the Bug
Automated:
pnpm install (the repo is pinned to 1.170.19)pnpm test — both tests fail: the pendingComponent appears during a
search-only navigation and during a param-only navigationpnpm add @tanstack/react-router@1.170.18 && pnpm test — both pass
Visual:
pnpm dev, open /projects/p1- Click "switch tab" (search-only) or "switch project" (param-only)
- The whole page flashes
PENDING (full-page spinner) on every click on
1.170.19; on 1.170.18 the content stays mounted
Expected behavior
As a user, I expected an in-app navigation on an already-mounted route to keep
the current UI while beforeLoad/loaders re-run (the 1.170.18 behavior), but
on 1.170.19 the mounted page is replaced by the pendingComponent on every
such navigation.
Screenshots or Videos
No response
Platform
- Router Version: 1.170.19 (regression from 1.170.18; router-core 1.171.16 vs 1.171.15)
- OS: macOS
- Browser: Firefox (also reproduced in jsdom)
- Bundler: vite
- Bundler Version: 7.x
Additional context
1.170.20 / router-core 1.171.17 only bump dependencies, so the behavior is
unchanged there. react-router pins router-core exactly, so pinning
1.170.18 is the workaround we ship today.
Which project does this relate to?
Router
Describe the bug
Since
@tanstack/react-router@1.170.19/@tanstack/router-core@1.171.16(the match-loading rewrite in #7805), a navigation that only changes search
params or a path param on an already-mounted route swaps the page to the
route's
pendingComponentwhile a parent layout's asyncbeforeLoadre-runs.On 1.170.18 the mounted UI stayed on screen during such navigations; the
pending component only appeared when there was nothing rendered yet (initial
load). With
defaultPendingMs: 0(pending immediately on cold start) anddefaultPendingMinMs: 250, our app now flashes a full-page spinner for atleast 250 ms on every in-app tab switch and every sibling-route switch,
because the layout's auth-guard
beforeLoaddoes a network round trip.Shape that reproduces it: a pathless layout route with an async
beforeLoad,a child route
/projects/$projectIdwithvalidateSearch, router optionsdefaultPendingMs: 0, defaultPendingMinMs: 250.Complete minimal reproducer
https://github.com/salty-flower/tsr-pending-navigation-repro
Steps to Reproduce the Bug
Automated:
pnpm install(the repo is pinned to 1.170.19)pnpm test— both tests fail: thependingComponentappears during asearch-only navigation and during a param-only navigation
pnpm add @tanstack/react-router@1.170.18 && pnpm test— both passVisual:
pnpm dev, open/projects/p1PENDING (full-page spinner)on every click on1.170.19; on 1.170.18 the content stays mounted
Expected behavior
As a user, I expected an in-app navigation on an already-mounted route to keep
the current UI while
beforeLoad/loaders re-run (the 1.170.18 behavior), buton 1.170.19 the mounted page is replaced by the
pendingComponenton everysuch navigation.
Screenshots or Videos
No response
Platform
Additional context
1.170.20 / router-core 1.171.17 only bump dependencies, so the behavior is
unchanged there.
react-routerpinsrouter-coreexactly, so pinning1.170.18 is the workaround we ship today.