Jeff Pal
Jeff Pal

Reputation: 1674

react-router-dom v6 nested routes doesn't work with element in the parent route

The Nested Routes example provided by React Router V6 docs does not work. I tried this with "react-router-dom": "^6.2.1" and the children routes doesn't work. It returns the root element when I try to access /parent or /parent/child:

<BrowserRouter>
  <Routes>
    <Route path="/" element={<div>Root</div>}>
      <Route path="parent" element={<div>Parent</div>}>
        <Route path="child" element={<div>Child</div>} />
      </Route>
    </Route>
  </Routes>
</BrowserRouter>

The /parent route just works if I remove the element from the root route: <Route path="/" >. But in this case I get the warning below, the page '/' is empty and the '/parent/child' still doesn't work.

Matched leaf route at location "/" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.

I would really appreciate any help to better understand this behavior.

Upvotes: 2

Views: 4157

Answers (1)

Drew Reese
Drew Reese

Reputation: 203587

For nested Route components, the parent layout component needs to render an Outlet for them to be rendered into.

Example:

<BrowserRouter>
  <Routes>
    <Route
      path="/"
      element={(
        <div>
          Root
          <Outlet /> // <-- nested routes rendered here
        </div>
      )}
    >
      <Route
        path="parent"
        element={(
          <div>
            Parent
            <Outlet /> // <-- nested routes rendered here
          </div>
        )}
      >
        <Route path="child" element={<div>Child</div>} />
      </Route>
    </Route>
  </Routes>
</BrowserRouter>

You need to read a bit further down in the doc you linked to get the explanation:

Notice the inner component that changed with the URL (<SentInvoices> and <Invoice>). The parent route (<Invoices>) is responsible for making sure the matching child route is rendered with <Outlet>. Here's the full example:

import { Routes, Route, Outlet } from "react-router-dom";

function App() {
  return (
    <Routes>
      <Route path="invoices" element={<Invoices />}>
        <Route path=":invoiceId" element={<Invoice />} />
        <Route path="sent" element={<SentInvoices />} />
      </Route>
    </Routes>
  );
}

function Invoices() {
  return (
    <div>
      <h1>Invoices</h1>
      <Outlet />
    </div>
  );
}

function Invoice() {
  let { invoiceId } = useParams();
  return <h1>Invoice {invoiceId}</h1>;
}

function SentInvoices() {
  return <h1>Sent Invoices</h1>;
}

Upvotes: 1

Related Questions