Search code examples
javascriptreactjsreact-routerreact-router-dom

nested routes do not render a new page using createBrowserRouter


I am unable to render my content to a new page, instead, it renders to the same page as its parent rather than the desired outcome of appearing as a new page when using dynamic URLs and createBrowserRouter. The desired outcome is when on the about page, user clicks one of the links and then a separate page is rendered with for AboutDetails component.

import React from 'react';
import { createBrowserRouter, RouterProvider  } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Skills from './Skills';
import Contact from './Contact';
import AboutDetails from './AboutDetails';

const router = createBrowserRouter([
  {
    path:'/',
    element: <Home />,
    children: [
      {
        path: 'about',
        element: <About />,
        children: [
          {
            path: ':item',
            element: <AboutDetails />
          }
        ]
      },
      {
        path: 'skills',
        element: <Skills />
      },
      {
        path: 'contact',
        element: <Contact />
      }
    ],
  },
]);

function App() {
  return (
    <>
      <RouterProvider router={router} />
    </>
  );
}

export default App;
import React from 'react'
import { Link } from 'react-router-dom';
import { Outlet } from "react-router-dom";

function Home() {
  return (
    <>
      <div style={{display: 'flex', justifyContent: 'space-evenly', textDecoration: 'none'}}>
        <Link to='/'>Home</Link>
        <Link to='about'>About</Link>
        <Link to='skills'>Skills</Link>
        <Link to='contact'>Contact</Link>
      </div>

      <main>
        <Outlet />
      </main>
    </>
  )
}

export default Home
import React from 'react';
import { Link, Outlet } from 'react-router-dom';

function About() {
  const listStuff = {
    links: ['prev-page', 'next-page', 'fast-fwd-page', 'fast-rwd-page']
  }
  return (
    <div>
      <h2>About</h2>
      <p>Damn it's about to go down!</p>
      <ul>
     {listStuff.links.map((item, idx) => (
      <li key={idx}>
        <Link to={`/about/${item}`}>{item}</Link>
        </li>
     ))}
     </ul>
    </div>
  );
}

export default About;
import React from 'react';
import { useParams, Outlet } from 'react-router-dom';

function AboutDetails() {
  const { item } = useParams()

  return (
    <>
      <div>AboutDetails</div>
      <p>I've extracted {item}</p>
    </>
  )
}

export default AboutDetails

Solution

  • If you do not want the about details to render on the same page under the about page content then you will need to unnest these routes so they are rendered independently. In other words, About and AboutDetails should be rendered on sibling routes.

    Examples:

    const router = createBrowserRouter([
      {
        path:'/',
        element: <Home />,
        children: [
          {
            path: 'about',
            element: <About />
          },
          {
            path: 'about/:item',
            element: <AboutDetails />
          },
          {
            path: 'skills',
            element: <Skills />
          },
          {
            path: 'contact',
            element: <Contact />
          }
        ],
      },
    ]);
    
    const router = createBrowserRouter([
      {
        path:'/',
        element: <Home />,
        children: [
          {
            path: 'about',
            children: [
              {
                index: true,
                element: <About />
              },
              {
                path: ':item',
                element: <AboutDetails />
              }
            ]
          },
          {
            path: 'skills',
            element: <Skills />
          },
          {
            path: 'contact',
            element: <Contact />
          }
        ],
      },
    ]);