Mastering React Router v6 Nested Routes and Layouts with <Outlet>
Learn how to create clean, hierarchical UIs in React Router v6 using nested routes and <Outlet> for shared layouts. Get a working example, common pitfalls, and how to verify the setup.
25 Aug 2026, 14:23 UTC

Why Nested Routes Matter
React Router v6 lets you declare a hierarchy of routes that maps directly to a component tree. When a parent route renders an <Outlet />, the router injects the matching child component into that spot. This pattern keeps navigation logic declarative, promotes shared UI (headers, sidebars), and enables code‑splitting on a per‑route basis.
Getting Started: A Minimal Example
Below is a full, self‑contained configuration that shows a dashboard layout with two child pages – Stats and Settings. All components are lazy‑loaded to illustrate route‑based code splitting.
// src/routes.js
import { createBrowserRouter, RouterProvider, Outlet, Link } from "react-router-dom";
import { Suspense, lazy } from "react";
// Lazy‑load child components
const Stats = lazy(() => import("./pages/Stats"));
const Settings = lazy(() => import("./pages/Settings"));
// Layout component – must render
function DashboardLayout() {
return (
Dashboard Header
Stats | Settings
Loading…}>
);
}
const router = createBrowserRouter([
{
path: "/dashboard",
element: , // parent layout
children: [
{ path: "stats", element: },
{ path: "settings", element: },
{ index: true, element: Welcome to the dashboard },
],
},
]);
export default function App() {
return ;
}
Key points:
- The parent route’s
elementcontains<Outlet />. Without it, child routes never render. - Child routes use relative paths ("stats", "settings"). Absolute paths would break the hierarchy.
- An
indexroute (no path) renders when the parent path matches exactly – useful for a default dashboard view. - Wrapping
<Outlet />in<Suspense>lets the router show a fallback while a lazy component loads.
Common Pitfalls & How to Avoid Them
1. Forgetting <Outlet />
If a layout component omits <Outlet />, React Router will silently render nothing for child routes. Check the console for the warning “No <Outlet /> found in the parent component.”
2. Misusing Index Routes
Index routes must be declared with index: true or an empty path: "". A non‑empty path on an index route will cause duplicate matches and can lead to unexpected navigation.
3. Mixing Absolute and Relative Paths
Inside nested route definitions, always use relative paths. If you need to navigate programmatically, set relative="path" on useNavigate or Link to preserve the current route context.
4. Over‑Nested Hierarchies
Deep nesting can make the component tree hard to reason about. When a layout only wraps a single child, consider flattening the structure or extracting the layout into a separate route group.
Verifying Your Setup
- Navigate Manually – Open
/dashboard/statsand/dashboard/settingsin the browser. The corresponding component should appear inside the dashboard layout. - Check the Console – Look for any warnings about missing
<Outlet />or duplicate routes. React will log “No<Outlet />found” if the layout is broken. - Inspect the Component Tree – Use React DevTools. The tree should show
DashboardLayoutas the parent, withStatsorSettingsas a child, depending on the URL. - Test Lazy Loading – Temporarily add a delay to the lazy import (e.g.,
import("./pages/Stats").then(m => new Promise(r => setTimeout(r, 2000)))). Navigate to the route and confirm the fallback UI appears for ~2 s.
When to Use Nested Routes vs. Flat Routes
Use nested routes when you have a shared UI that should persist across several sub‑pages – a common header, breadcrumb, or sidebar. For simple, unrelated routes, a flat structure keeps the configuration easier to maintain.
Conclusion
Nested routes and <Outlet /> are the backbone of hierarchical navigation in React Router v6. By declaring a clear parent–child relationship, you keep routing logic declarative, enable shared layouts, and gain the ability to lazy‑load each child component. Just remember to render an <Outlet />, use relative paths, and verify with the console and DevTools to avoid the most common mistakes.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.