Learn how to use nested routes and the Outlet component in React Router to build consistent page layouts, reduce code duplication, and improve UI design.
Previously in this course, we explored Introduction to React Router: Building Multi-Page SPAs and expanded that knowledge by implementing Dynamic Routing with URL Parameters in React Router. While we can now navigate between pages, our current approach forces us to manually include navigation bars or sidebars in every single component.
Today, we move beyond simple page-to-page navigation. We’ll learn how to structure our application using nested routes to create persistent UI layouts, ensuring our dashboard feels like a cohesive single-page application rather than a collection of disconnected files.
In a standard web application, "layout" usually refers to the parts of the page that don't change when you navigate—think of a sidebar, a header, or a footer. Without nested routes, you would find yourself importing these components into every page component, which is a maintenance nightmare.
Nested routes allow us to define a parent route that acts as a container for shared UI, while "child" routes represent the specific content that changes within that container.
The mechanism that powers this is the Outlet component. When you define a route hierarchy, the Outlet tells React Router: "Render the child route component right here." It’s essentially a placeholder that gets swapped out dynamically as the URL changes, while the parent layout stays mounted and interactive.
Let’s advance our dashboard project. We want a persistent sidebar that stays on screen while the main content area updates.
First, we define a component that contains the common UI.
JSXimport { Outlet, Link } from CE9178">'react-router-dom'; export default function DashboardLayout() { return ( <div className="dashboard-container"> <nav className="sidebar"> <ul> <li><Link to="/dashboard">Overview</Link></li> <li><Link to="/dashboard/settings">Settings</Link></li> </ul> </nav> <main className="content"> {/* This is where child routes will render */} <Outlet /> </main> </div> ); }
Now, we inform react-router-dom about this relationship. We nest the specific dashboard pages inside the parent DashboardLayout route.
JSXimport { BrowserRouter, Routes, Route } from CE9178">'react-router-dom'; import DashboardLayout from CE9178">'./DashboardLayout'; import Overview from CE9178">'./Overview'; import Settings from CE9178">'./Settings'; function App() { return ( <BrowserRouter> <Routes> <Route path="/dashboard" element={<DashboardLayout />}> <Route index element={<Overview />} /> <Route path="settings" element={<Settings />} /> </Route> </Routes> </BrowserRouter> ); }
In this configuration, when the user visits /dashboard, the DashboardLayout renders, and the Overview component is injected into the Outlet. When they visit /dashboard/settings, the DashboardLayout remains mounted, but the Outlet swaps Overview for Settings.
DashboardLayout.jsx following the example above.App.jsx routing configuration to nest at least two child routes under a single parent layout.console.log in DashboardLayout and navigate between pages—it should only log once).<Outlet />: If you define nested routes but forget to place the Outlet component in your parent layout, the child routes will simply fail to render. The parent will show up, but the main content area will remain empty.Link components inside the sidebar, ensure you are using relative paths (e.g., to="settings") or absolute paths that match the route tree. Mixing them up is the most common cause of "404 Not Found" errors during navigation.By using nested routes, we've successfully decoupled our UI structure from our page content. This pattern not only cleans up our component files by removing repeated navigation logic but also enables smoother UI transitions, as the parent layout component isn't destroyed and re-mounted during navigation. This is a foundational step toward building the Advanced React Patterns: Scaling Your Architecture for Production we’ll need for the rest of our dashboard.
Up next: We will secure our dashboard by creating Protected Routes that redirect unauthenticated users away from private content.
Learn how to build a robust dashboard navigation UI by integrating sidebar layouts, private route guards, and authentication state in React.
Read moreLearn how to use the useNavigate hook in React Router to trigger navigation on events, handle redirects, and manage complex user flows in your dashboard.
Nested Routes and Layouts
Asynchronous Data Lifecycle
Caching Strategies with React Query
Mutations and Data Updates
Synchronizing Client and Server State
Integrating Live Data into the Dashboard
Error Handling and Loading UI
Controlled vs Uncontrolled Components
Real-time Form Validation
Schema-based Validation with Zod
Handling Multi-step Forms
Optimizing Form Submissions
Performance Profiling with React DevTools
Refactoring for Scalability
Finalizing Dashboard Data Flow
Deploying the Application
Advanced Hook Composition
Implementing Middleware for State
Advanced Context Patterns
Router Loaders and Data Prefetching
Complex Route Guards
Handling Large Datasets in UI
Testing Hooks and Components
Managing Global Modals
Implementing Keyboard Shortcuts
Optimizing Asset Loading
Internationalization Basics
Managing WebSocket Connections