'Define React Router Routes In Another Components

I am using react-router-dom 5.2.0. I want 2 files that define all of my routes. 1 file for public routes, 1 file for private. The right component renders when I hit the home route, but not the /content route.

App.jsx returns:

<BrowserRouter>
  <Switch>
    <PublicRoutes />
    <PrivateRoutes />
  </Switch>
</BrowserRouter>

PublicRoutes.jsx returns:

<Route path="/" exact render={() => <h1>home route</h1>} />

And PrivateRoutes.jsx returns:

<Route path="/content" exact render={() => <h1>Content Route</h1>} />

I am able to load / with "home route", but nothing renders when I hit the /content url.



Solution 1:[1]

Those Switches need to go inside your wrapper routes, like so:

import { BrowserRouter, Switch, Route } from "react-router-dom";
import "./styles.css";

const PublicRoutes = () => (
  <Switch>
    <Route path="/" exact render={() => <h1>home route</h1>} />
  </Switch>
);
const PrivateRoutes = () => (
  <Switch>
    <Route path="/content" exact>
      <h1>Content Route</h1>
    </Route>
  </Switch>
);

export default function App() {
  return (
    <BrowserRouter>
      <PublicRoutes />
      <PrivateRoutes />
    </BrowserRouter>
  );
}

https://codesandbox.io/s/shy-river-ysv4w?file=/src/App.js

Solution 2:[2]

Issue

The Switch component returns and renders the first matching Route or Redirect component. PublicRoutes nor PrivateRoutes are neither, the PublicRoutes is returned by default.

Switch

Renders the first child <Route> or <Redirect> that matches the location.

Solution

You'll need to render a Route in the Switch that checks the authentication condition and conditionally render one or the other.

<BrowserRouter>
  <Switch>
    <Route
      render={(routeProps) => authCondition ? (
        <PublicRoutes {...routeProps} />
      ) : (
        <PrivateRoutes {...routeProps} />
      )}
    />
  </Switch>
</BrowserRouter>

If your public and private routes are split on the path then you can likely more simply render each on their perspective paths.

<BrowserRouter>
  <Switch>
    <Route path="/content" component={PrivateRoutes} />
    <Route path="/" component={PublicRoutes} />
  </Switch>
</BrowserRouter>

With either you will then likely need to render a nested Switch that builds on the base path of each if you've further nested routes.

Solution 3:[3]

in react router v6 it is possible by using outlet base on docs

or you should use this

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="dashboard/*" element={<Dashboard />} />
    </Routes>
  );
}

function Dashboard() {
  return (
    <div>
      <p>Look, more routes!</p>
      <Routes>
        <Route path="/" element={<DashboardGraphs />} />
        <Route path="invoices" element={<InvoiceList />} />
      </Routes>
    </div>
  );
}

please Pay attention to * end of path="dashboard/*"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 codemonkey
Solution 2 Drew Reese
Solution 3