ssr:false: redirect thrown in a child beforeLoad during the initial load blanks the app (MatchInner throws `undefined`), reproducer for #7910
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 48/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- react, typescript
Direzione di ricerca
Start by tracing hydration and the redirected load through MatchInnerImpl, getMatchPromise, CatchBoundary, and loadRouteMatch; the issue gives a reproducible timing scenario but no test file or code locations. Reproduce with the supplied ssr: false parent and child beforeLoad redirect, adding router.invalidate() during the redirected load. Done means the initial page no longer blanks and the redirect reaches the destination reliably.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Versions:
- @tanstack/react-router 1.170.18
- @tanstack/router-core 1.171.15
- @tanstack/react-start 1.167.x (start-client-core 1.170.14)
- React 19.2
- Vite 8.1, dev mode
Describe the bug
A full page load of a URL under an ssr: false layout, where a child route's async beforeLoad throws redirect(), can leave the page blank. The console shows Uncaught undefined and "An error occurred in the component".
Navigating to the same URL client-side works.
This is the issue reported in #7910, which was closed for lack of a reproducer. Here is one with no .preload() forwarding.
Minimal reproduction
// routes/zzrepro.tsx
export const Route = createFileRoute("/zzrepro")({
ssr: false,
beforeLoad: async () => { await wait(200); return { user: { id: "x" } } },
component: () => <Outlet />,
})
// routes/zzrepro.a.tsx
export const Route = createFileRoute("/zzrepro/a")({
beforeLoad: async () => { await wait(200); throw redirect({ to: "/zzrepro/b" }) },
component: () => <div>A</div>,
})
// routes/zzrepro.b.tsx
export const Route = createFileRoute("/zzrepro/b")({
beforeLoad: async () => { await wait(200) },
component: () => <div>B rendered OK</div>,
})
In our app, the redirect alone was enough to blank the page.
In this synthetic version it reproduces deterministically if router.invalidate() is also called while the redirected load is in flight, about 500–900 ms after page load.
For example, Supabase's onAuthStateChange emits SIGNED_IN on every page load. A root-level listener that calls router.invalidate() on it hits this window.
Analysis
- The
ssr: falsematch is dehydrated aspending. On the client,hydrate()puts it in the active matches, androuter.load()runs the guards. - The child throws a redirect.
navigate({ replace: true })starts a new load whose pending matches reuse the same id for thessr: falselayout. They share_nonReactive. - That load finishes the layout match.
loadRouteMatchresolves and clears_nonReactive.loadPromise. This happens beforeonReadycommits the pending matches. - React renders the still-active stale snapshot (
status: "pending").MatchInnerImpldoesthrow getMatchPromise(match, "loadPromise"), which isundefined. CatchBoundarystoresundefinedas the error. That is falsy, so it re-renders its children, which throw again. React gives up and unmounts the root.- The router state afterwards is correct (all matches
success), but nothing is mounted.router.state.statusstayspendingforever.
Workaround we ship (patch-package)
In MatchInnerImpl's getMatchPromise:
return router.getMatch(match.id)?._nonReactive[key]
?? match._nonReactive[key]
?? router.latestLoadPromise
?? new Promise((resolve) => setTimeout(resolve, 0))
Suggested fixes
- Never throw a non-thenable from the pending branches.
- Or keep
loadPromisealive until the pending matches are committed. - Separately,
CatchBoundarycould treat a thrownundefinedas an error, so it renders theerrorComponentinstead of looping.
- Lingua principale
- TypeScript
- Stelle
- 15.2k
- Fork
- 1.9k
- Merge medio
- 1g 13h
- PR unite (30g)
- 76
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di TanStack/router
-
router.startViewTransition leaves the ready/finished promises unhandled, so a skipped transition throws an unhandled AbortErrorForse già presa @unjica l’ha presa 2 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
TanStack/router#8776 · 3 commenti · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
Router devtools crash when search params contain a BigInt (JSON.stringify in history tracking)Forse già presa @A-Raphie l’ha presa 6 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
docs: `createLink` has no API reference page; 3 how-to guides link to a missing `#createlink` anchorForse già presa @A-Raphie l’ha presa 6 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
I maintainer di solito rispondono entro 1 giorno
-
Inline scripts are duplicated after hydration when the CSP nonce is sent in a headerForse già presa @gabriel-le l’ha presa 27 giorni fa. Aperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
I maintainer di solito rispondono entro 1 giorno
-
start-plugin-core: sitemap lastmod and pages.json lastBuilt are stamped with the build's wall clock (no SOURCE_DATE_EPOCH support)Forse già presa @treadnot l’ha presa 28 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di TanStack/router
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 70/100
microsoft/playwright#43640 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
grasshopper-protocol/grsshppr#172 ·
I maintainer di solito rispondono entro 1 giorno
-
bug help wanted
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
Tencent/teamai-cli#1397 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
DouyinFE/semi-design#3641 ·
I maintainer di solito rispondono entro 3 giorni
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
I maintainer di solito rispondono entro 1 giorno