Search code examples
javascriptreactjsreact-router-dom

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


I'm using React Router v6 and am creating private routes for my application.

In file PrivateRoute.js, I've the code

import React from 'react';
import {Route,Navigate} from "react-router-dom";
import {isauth}  from 'auth'

function PrivateRoute({ element, path }) {
  const authed = isauth() // isauth() returns true or false based on localStorage
  const ele = authed === true ? element : <Navigate to="/Home"  />;
  return <Route path={path} element={ele} />;
}

export default PrivateRoute

And in file route.js I've written as:

 ...
<PrivateRoute exact path="/" element={<Dashboard/>}/>
<Route exact path="/home" element={<Home/>}/>

I've gone through the same example React-router Auth Example - StackBlitz, file App.tsx

Is there something I'm missing?


Solution

  • I ran into the same issue today and came up with the following solution based on this very helpful article by Andrew Luca

    In PrivateRoute.js:

    import React from 'react';
    import { Navigate, Outlet } from 'react-router-dom';
    
    const PrivateRoute = () => {
        const auth = null; // determine if authorized, from context or however you're doing it
    
        // If authorized, return an outlet that will render child elements
        // If not, return element that will navigate to login page
        return auth ? <Outlet /> : <Navigate to="/login" />;
    }
    

    In App.js (I've left in some other pages as examples):

    import './App.css';
    import React, {Fragment} from 'react';
    import {BrowserRouter as Router, Route, Routes} from 'react-router-dom';
    import Navbar from './components/layout/Navbar';
    import Home from './components/pages/Home';
    import Register from './components/auth/Register'
    import Login from './components/auth/Login';
    import PrivateRoute from './components/routing/PrivateRoute';
    
    const App = () => {
      return (
        <Router>
          <Fragment>
            <Navbar/>
            <Routes>
              <Route exact path='/' element={<PrivateRoute/>}>
                <Route exact path='/' element={<Home/>}/>
              </Route>
              <Route exact path='/register' element={<Register/>}/>
              <Route exact path='/login' element={<Login/>}/>
            </Routes>
          </Fragment>
        </Router>
        
      );
    }
    

    In the above routing, this is the private route:

    <Route exact path='/' element={<PrivateRoute/>}>
          <Route exact path='/' element={<Home/>}/>
    </Route>
    

    If authorization is successful, the element will show. Otherwise, it will navigate to the login page.