The one idea
Routes nest like Russian dolls: a parent renders <Outlet/>, the matched child fills it. And context set at the root flows DOWN to every descendant through createRootRouteWithContext — no prop-drilling across the tree. Each route may augment the context in beforeLoad, and the union is inherited by all its children.
Two mechanisms, one route tree. Nesting is about rendering:
<Outlet/> renders exactly one matched child (or null if
there is none). Context is about data: the router carries a
context object down the match chain; a route reads the merged set via
Route.useRouteContext(). The two are independent but compose — a deeply
nested leaf renders inside every ancestor's <Outlet/> and
reads every ancestor's context.
The nesting + context visualizer — click a route, see its render chain & context
Left: the curated src/routes/ tree (6 routes). Right: type a URL (or click a
sample) — the resolver shows the component render chain with
<Outlet/> markers, then the context each level can read.
Notice the root context key queryClient reaches every leaf, while
fetchPosts (added in posts's beforeLoad) only
appears under /posts — never on the / sibling branch.
$param
beforeLoad adds context
The render tree — <Outlet/> is where the matched child goes
Every layout in the chain renders exactly one <Outlet/>
— the slot the next matched route fills. A chain of N routes has
N−1 outlets (the leaf has none). If a route defines no
component, the router renders an <Outlet/> automatically.
Resolve a URL above to see its chain render here.
Context flow — set at the root, inherited DOWN, augmented per route
The root context (queryClient) is provided at createRouter({ context })
and typed with createRootRouteWithContext. Each route's
beforeLoad may return an object that is merged in; the
union is available to that route's loader, its component
(via useRouteContext()), and every child. gold
= root context, cyan = added at this level,
grey = inherited from an ancestor.
Resolve a URL to see the context each matched route reads.
Concept → what it does → example
| Concept | Does | Example |
|---|---|---|
<Outlet/> |
Renders the one next matched child route (or null). Takes no props. |
<div><h1/> <Outlet/> </div> |
| nested route | A child route whose URL extends the parent's; the parent wraps it through <Outlet/>. |
posts/$postId.tsx renders inside posts.tsx |
createRootRouteWithContext<T>()() |
Creates the root route AND constrains the typed root context T. Double-called factory. |
createRootRouteWithContext<{queryClient}>()() |
createRouter({ context }) |
Provides the initial root context values (must satisfy T). |
createRouter({ routeTree, context:{ queryClient } }) |
beforeLoad |
Runs serially, per-navigation, before the loader. May return an object merged into this route's context (inherited by children). | beforeLoad: () => ({ fetchPosts }) |
Route.useRouteContext() |
Reads the merged context (root + every ancestor's beforeLoad) inside a route component. |
const { queryClient } = Route.useRouteContext() |
| context inheritance | Context merges DOWN the match chain: each child sees the union of all ancestors' context. | leaf sees queryClient + fetchPosts + postMeta |
no component |
If a route omits component, the router renders an <Outlet/> for it automatically. |
a layout route that only wraps, renders nothing of its own |