Uh oh!
There was an error while loading. Please reload this page.
Replies: 1 comment 1 reply
There's a documented pattern for exactly this in the router-context guide, and it sidesteps the three approaches you listed because it doesn't try to make exportconstRoute=createRootRoute({component: ()=>{constmatches=useRouterState({select: (s)=>s.matches})constmatchWithTitle=[...matches].reverse().find((d)=>d.context.getTitle)consttitle=matchWithTitle?.context.getTitle()||'My App'return(<html><head><title>{title}</title></head><body>{/* ... */}</body></html>)},})The key difference from This is also why it avoids your two failure modes: it goes through the router's own |
Uh oh!
There was an error while loading. Please reload this page.
Problem
In a SPA using the recommended TanStack Query integration, loaders typically call
queryClient.ensureQueryData()without awaiting so navigation stays instant, and components read the data withuseSuspenseQuery. In this setuphead({ loaderData })can't produce a dynamic title:loaderDatais empty whenhead()runs, andhead()is never re-invoked once the data lands in the cache.Current options all have drawbacks:
useEffect+document.titleafter Suspense resolves → works, but bypassesHeadContent, and only by relying on the (undocumented) fact thatHeadContentwon't rewrite an unchanged title.<title>hoisting → conflicts with the<title>thatHeadContentrenders (duplicate tags, first-in-document wins).Proposal
First-class support for a two-phase title: a static fallback shown at navigation, replaced when async data resolves. Possible shapes:
head()when an unawaited/deferred promise returned from the loader resolves (Await-awarehead), oruseHead()hook or<RouteHead title={...} />component that participates inHeadContent's dedupe/override chain.Related
document.titleworkaroundheadrunning before the loader finishes (the awaited case)All reactions