Nesting

Since routes are regular React components, they may be rendered anywhere in the app, including in child elements. This helps when it's time to code-split your app into multiple bundles because code-splitting a React Router app is the same as code-splitting any other React app.

Nested routes now use actual JSX nesting instead of a hook: a parent <Route> can contain child <Route>s (including an "index" route for the parent's own URL with nothing extra appended), and the parent's element renders an <Outlet /> wherever the matched child should appear. Links to a nested route can be written relative to the current route (no leading slash) instead of manually concatenating a "url" string, so this used to require useRouteMatch() and now needs no extra hook at all.


import React from "react";
import { BrowserRouter as Router, Routes, Route, Link, Outlet, useParams } from "react-router";

export default function NestingExample() {
  return (
    <Router>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/topics">Topics</Link></li>
        </ul>
        <hr />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/topics" element={<Topics />}>
            <Route index element={<h3>Please select a topic.</h3>} />
            <Route path=":topicId" element={<Topic />} />
          </Route>
        </Routes>
      </div>
    </Router>
  );
}
function Home() { return (<div><h2>Home</h2></div>); }
function Topics() {
  // These links have no leading slash, so they resolve relative to "/topics"
  // automatically - no more manually building a `${url}/...` string.
  return (
    <div>
      <h2>Topics</h2>
      <ul>
        <li><Link to="rendering">Rendering with React</Link></li>
        <li><Link to="components">Components</Link></li>
        <li><Link to="props-v-state">Props v. State</Link></li>
      </ul>
      {/* Renders whichever child route (the index route, or :topicId) matched */}
      <Outlet />
    </div>
  );
}
function Topic() {
  // The <Route> that rendered this component has a path of "/topics/:topicId".
  // The ":topicId" portion of the URL is a placeholder we read with useParams().
  let { topicId } = useParams();
  return (<div><h3>{topicId}</h3></div>);
}