2

I am having some issues with the following problem.

The design brief contains 3 different pages. 2 has the same layout for the Navbar and Footer, but the third page has a different style for those components. I am using the latest react-router-dom v6, and it has changed a lot compare to the older versions.

So my goal is to render the 3rd page without the footer and navbar, and give its own style to it with new components. Although in my App.js, I rendered this 2 component for every page to make it more efficient and avoid duplicate codes.

App.js

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

import Navigation from "./Components/Navigation/Navigation.components";
import Footer from "./Components/Footer/Footer.components";

import HomePage from "./Pages/HomePage/Home.pages";
import Portfolio from "./Pages/PortfolioPage/Portfolio.pages";
import Contact from "./Pages/ContactPage/Contact.pages";

import './App.scss';

function App() {
  return (
    <div className="App">
      <Navigation />
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="portfolio" element={<Portfolio />} /> // this page needs different components
        <Route path="contact" element={<Contact />} />
      </Routes>
      <Footer />
    </div>
  );
}

export default App;

I tried a solution to write a simple wrapper around Route that need to render Navigation and use the normal Route for a component that doesn't need the generic Navigation,like this:

const RouteWithNavbar = ({exact, path, component:Component, ...rest}) => {
   return <Route exact={exact} path={path} {...rest} render={(routeProps) => {
      return <><Navigation {...routeProps}/><Component {...routeProps}/>
   }}
   />
}

    function App() {
      return (
        <div className="App">
          <Navigation />
          <Routes>
            <RouteWithNavbar path="/" element={<HomePage />} />
            <Route path="portfolio" element={<Portfolio />} /> // this page needs different components
            <RouteWithNavbar path="contact" element={<Contact />} />
          </Routes>
          <Footer />
        </div>
      );
    }
    
    export default App;

but this solution doesn't work, because

All component children of < Routes > must be a < Route > or <React.Fragment>

Any idea would be highly appreciated, as I'm scrolling through of the react-dom docs, and can't see between the lines. There must be something obvious solution what I can't see by stressing on it too much.

Benji
  • 280
  • 3
  • 15

1 Answers1

5

In react-router-dom version 6 gone are the use of custom route components. Create a layout wrapper component that renders children routes into an Outlet component.

Example:

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

const FullLayout = () => (
  <div /* apply any styling here, or none */ >
    <Navigation />
    <Outlet />
    <Footer />
  </div>
);

const MinimalLayout = () => (
  <div /* apply any styling here, or none */ >
    <Outlet />
  </div>
);

Wrap the routes you want rendered into each layout.

function App() {
  return (
    <div className="App">
      <Routes>
        <Route path="/*" element={<FullLayout />}>
          <Route index element={<HomePage />} />
          <Route path="contact" element={<Contact />} />
        </Route>
        <Route path="/portfolio" element={<MinimalLayout />}>
          <Route path="/portfolio" element={<Portfolio />} />
        </Route>
      </Routes>
    </div>
  );
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181