Ancross
Ancross

Reputation: 25

React Router removes parent component when path extends

I'm trying to have routing withing an existing route, but when I try to apply more routes on top of the existing route, the parent component is no longer rendered.

Here are my parent routes:

<Routes>
    <Route exact path = '/Music-Shop' element={<LandingPage />} />
    <Route path = '/Music-Shop/Products' element={<ProductsHome />} />
</Routes>

I want to have a Link component lead to /Products/product-category inside the ProductsHome component, and keep it rendering

<Link 
  to = '/Music-Shop/Products/Instruments' 
  className = 'sidebarLink'
/> 

How can I keep extending the /Products path while still rendering the ProductsHome Component?

Upvotes: 1

Views: 758

Answers (2)

Drew Reese
Drew Reese

Reputation: 203552

There are a couple of methods to achieve this.

Use nested routes with a parent layout route.

Render ProductsHome as a layout route that renders the common UI you want and an Outlet component for nested routes to render their content into.

Example:

import { Outlet } from 'react-router-dom';

const ProductsHome = () => {
  ...

  return (
    <div /* parent UI layout design */>
      ... Products home UI ...

      <Outlet />
    </div>
  );
};

Render ProductsHome as a layout route and wrap the nested routes you want to render with the common UI.

<Routes>
  <Route path='/Music-Shop'>
    <Route index element={<LandingPage />} />
    <Route path='Products' element={<ProductsHome />}>
      <Route path='Instruments' element={<Instruments />} />
      ... other nested routes ...
    </Route>
  </Route>
</Routes>

Use descendent routes.

Render ProductsHome on a route with a trailing wildcard matcher "*" character so descendent routes can be matched and rendered.

<Routes>
  <Route path='/Music-Shop'>
    <Route index element={<LandingPage />} />
    <Route path='Products/*' element={<ProductsHome />} />
  </Route>
</Routes>

Update ProductsHome to render a Routes component wrapping the descendent routes.

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

const ProductsHome = () => {
  ...

  return (
    <div /* parent UI layout design */>
      ... Products home UI ...

      <Routes>
        <Route path='Instruments' element={<Instruments />} />
        ... other descendent routes ...
      </Routes>
    </div>
  );
};

Upvotes: 1

Ancross
Ancross

Reputation: 25

Add a /:type to the end of the path you want the parent component to render with

<Route path = '/Music-Shop/Products/:type' element={<ProductsHome />} />

In the child Component:

import { useParams } from 'react-router-dom'

export default function ProductDisplay() {

  const { type } = useParams();

  return (
    <>
      {type === 'Instruments' && <Instruments />}
    <>
  )
}

Upvotes: 0

Related Questions