Capítulo 4 de 24
The code-based twin of the basic file-based example: same posts list, dynamic $postId route, and nested pathless layouts, but built with createRoute/addChildren, plus it demonstrates splitting a route's component into a separate lazily-loaded file with .lazy() and createLazyRoute, code-based routing's answer to file-based route code splitting.
.lazy(() => import(...))@tanstack/react-router, @tanstack/react-router-devtools, redaxios. No @tanstack/router-plugin since there's no codegen.src/main.tsx defines rootRoute, indexRoute, a postsLayoutRoute (loader only, component deferred), a pathlessLayoutRoute with nested pathlessLayoutARoute/pathlessLayoutBRoute, then assembles everything with addChildren. src/posts.lazy.tsx holds the actual PostsLayoutComponent UI, loaded on demand. src/posts.ts holds the plain data-fetching functions (fetchPosts, fetchPost).// src/main.tsx
export const postsLayoutRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'posts',
loader: () => fetchPosts(),
}).lazy(() => import('./posts.lazy').then((d) => d.Route))
const postRoute = createRoute({
getParentRoute: () => postsLayoutRoute,
path: '$postId',
errorComponent: PostErrorComponent,
loader: ({ params }) => fetchPost(params.postId),
component: PostComponent,
})
// src/posts.lazy.tsx
export const Route = createLazyRoute('/posts')({
component: PostsLayoutComponent,
})
function PostsLayoutComponent() {
const posts = Route.useLoaderData()
return (
<div className="p-2 flex gap-2">
<ul className="list-disc pl-4">
{posts.map((post) => (
<li key={post.id}>
<Link to="/posts/$postId" params={{ postId: post.id }}>
{post.title.substring(0, 20)}
</Link>
</li>
))}
</ul>
<Outlet />
</div>
)
}
.lazy(() => import(...)) splits a route's component into its own JS chunk while loader, path, and getParentRoute stay in the eagerly-loaded route tree; createLazyRoute('/posts') in the split file must reference the same path string to reattach to the parent route definition..lazy() is the direct equivalent of file-based routing's automatic .lazy.tsx splitting: keep data/loader logic in the main bundle, defer UI code.Link to="/posts/$postId" params={{ postId: post.id }} gives compile-time checking that the param object matches the route's declared dynamic segments._pathlessLayout -> _nestedPathlessLayout -> route-a/route-b) works identically to file-based routing; only the syntax for declaring the nesting differs (id: '_pathlessLayout' plus addChildren versus filenames).src/routes/*.tsx files instead of hand-assembled with addChildren.createRoute/addChildren pattern, without loaders or lazy splitting.