Import routes in React with react router

Viewed 2168

I am starting with React and trying to separate the routes into their respective files. I am using react router v6.

So I want to import the admin routes in my routes.jsx like this:

import React from 'react';
import {
  BrowserRouter, Routes, Route,
} from 'react-router-dom';
import AdminRoutes from './admin/adminRoutes';

const routes = () => (
  <BrowserRouter>
    <Routes>
      <AdminRoutes />
      <Route path="/home" element="User template" />
      <Route path="/" element="Login Template" />
      <Route path="/register" element="Register Template" />
    </Routes>
  </BrowserRouter>
);

export default routes;

and in my adminRoutes.jsx I have:

import React from 'react';
import { Route } from 'react-router-dom';

const adminRoutes = () => (
  <Route path="admin/*">
    <Route path="countries" element="countries" />
    <Route path="tournaments" element="Tournaments" />
  </Route>
);

export default adminRoutes;

I get the error:

Error: [adminRoutes] is not a < Route> component. All component children of < Routes> must be a < Route > or < React.Fragment >

3 Answers

In react-router-dom v6 the Routes component can have only Route or React.Fragment as children, and Route components only Routes or other Route components as parent. It's an invariant RRDv6 enforces.

Convert adminRoutes into a React component and ensure the routed components are rendered on the element prop as JSX. React component names use PascalCase. Move the path="/admin/*" to Routes component which will render this component.

const AdminRoutes = () => (
  <Routes>
    <Route path="countries" element="countries" />
    <Route path="tournaments" element="Tournaments" />
  </Routes>
);

export default AdminRoutes;

Render AdminRoutes into the router on its own route.

const Routes = () => (
  <BrowserRouter>
    <Routes>
      <Route path="/admin/*" element={<AdminRoutes />} />
      <Route path="/home" element="User template" />
      <Route path="/" element="Login Template" />
      <Route path="/register" element="Register Template" />
    </Routes>
  </BrowserRouter>
);

Demo opens to "/admin/countries" and renders "countries".

Edit import-routes-in-react-with-react-router

This is happening because

const adminRoutes = () => (
  <Route path="admin/*">
    <Route path="countries" element="countries" />
    <Route path="tournaments" element="Tournaments" />
  </Route>
);

when you are doing this, you are creating a standalone Component that underwent all the things a React Component do, and thus react-router-dom is not accepting it.

For explanation, let's suppose if you treat it as a valid option to be used as a child of Routes as it is only returning <Route/> from it, but here one thing to notice is, you can add all the hooks like useEffect and all which makes it more than just a <Route /> and because of this reason, react-router-dom is not allowing it.

What you can do is, instead of exporting it as a React Component, you can export it as a React Element and this will be allowed.

const AdminRoutes = (<Routes>
    <Route path="countries" element="countries" />
    <Route path="tournaments" element="Tournaments" />
  </Routes>);

export default AdminRoutes;

and then use it as {AdminRoutes} inside the <Routes></Routes>.

Here is an example code https://codesandbox.io/s/happy-swartz-ikqdn?file=/src/App.js . Goto /te to see it working.

You can read more about Element and Component at https://reactjs.org/docs/rendering-elements.html .

Note: Follow the consecutive links to know about component and difference as well.

You can try this. You should wrap with Routes component when import another route.

import React from 'react';
import {
  BrowserRouter, Routes, Route,
} from 'react-router-dom';
import AdminRoutes from './admin/adminRoutes';

const routes = () => (
  <BrowserRouter>
    <AdminRoutes />
    <Routes>
      <Route path="/home" element="User template" />
      <Route path="/" element="Login Template" />
      <Route path="/register" element="Register Template" />
    </Routes>
  </BrowserRouter>
);

export default routes;

and

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

const adminRoutes = () => (
  <Routes>
    <Route path="admin/*">
      <Route path="countries" element="countries" />
      <Route path="tournaments" element="Tournaments" />
    </Route>
  </Routes>
);

export default adminRoutes;

demo

Related