Modern React 30: Routing and nested layouts
This is part 30 of the Modern React development series.
Routing connects the URL to the UI. Nested layouts make the route tree visible in the screen structure, so shared shells stay mounted while child route content changes.
Concept
A route maps a URL pattern to UI and often to data. A nested layout is parent route UI that wraps child routes, usually with an outlet or children slot where the child route renders.
Terms
- Route: A mapping from URL state to UI and route behavior.
- Nested layout: A parent route wrapper shared by child routes.
- Outlet: The placeholder where a matched child route renders.
- URL state: Application state represented in the path or query string.
Mental model
Think of routing as a file cabinet. The cabinet frame stays put, drawers open for sections, and documents change inside the drawer without rebuilding the whole cabinet.
How it is used
Use nested layouts for dashboards, account settings, project areas, admin screens, tabbed route sections, documentation, and any place where navigation chrome should persist while content changes.
How to use it
- Design URLs around resources and user tasks.
- Place shared navigation and shell UI in parent layouts.
- Render child route content through an outlet or framework
childrenslot. - Keep route params and query values validated at the route boundary.
- Use loading and error boundaries at route levels that match user-visible sections.
Example: Generic account layout
import type { ReactNode } from "react";
type AccountLayoutProps = { children: ReactNode;};
export function AccountLayout({ children }: AccountLayoutProps) { return ( <section className="account-layout"> <nav aria-label="Account settings"> <a href="/account/profile">Profile</a> <a href="/account/security">Security</a> </nav> <main>{children}</main> </section> );}Profile settings
Frameworks differ in how they provide child route content, but the layout model is the same.
Example: Route config sketch
import { AccountLayout } from "./AccountLayout";import { ProfilePage } from "./ProfilePage";import { SecurityPage } from "./SecurityPage";
const routes = [ { path: "/account", element: <AccountLayout />, children: [ { path: "profile", element: <ProfilePage /> }, { path: "security", element: <SecurityPage /> }, ], },];const routes = [
{
path: "/account",
element: <AccountLayout />,
children: [
{ path: "profile", element: <ProfilePage /> },
{ path: "security", element: <SecurityPage /> },
],
},
];
The route shape mirrors the UI shape: account shell first, child page second.
Details to watch
- URL durability: A routed state can be refreshed, shared, bookmarked, and opened in a new tab.
- Layout state: State in a parent layout can persist while child routes change.
- Params: Path and search params are strings at the browser boundary. Parse them before using typed assumptions.
- Data ownership: Prefer route data APIs when the data belongs to navigation rather than one small component.
Series navigation
- Previous: Part 29: ESLint, TypeScript, formatting, and CI gates
- Next: Part 31: Data fetching with a cache
- Series index: Modern React development