0

I am trying to implement a PrivateRoute logic with the newly released Router but it seems it doesn't work as expected..


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

import LogInPage from "./pages/LogIn";
import DashboardPage from "./pages/Dashboard";

function PrivateRoute({ path, element }) {
  const auth = true;

  return (
    <Route
      path={path}
      element={auth === true ? element : <Navigate replace to="/login" />}
    />
  );
}

function App() {
  return (
    <Routes>
      <Route path="/*" element={<PageNotFound />} />
      <Route path="/" element={<Navigate replace to="/dashboard" />} />
      <Route path="/login" element={<LogInPage />} />
      <PrivateRoute
        path="/dashboard"
        element={<DashboardPage />}
      />
    </Routes>
  );
}

export default App;


What am I missing? Isn't the PrivateRoute component still a Route component if it is returning a Route ?

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Razvan Cretu
  • 33
  • 3
  • 9
  • 1
    See the official react-router v6 [auth example](https://github.com/remix-run/react-router/blob/main/docs/examples/auth.md) for private routing. – Matt Carlotta Nov 06 '21 at 22:04
  • Thanks, I tried the way you mentioned and it works perfectly.. Unfortunately I am more interested the way I specified above if it works... To me that seems more convenient rather than wrapping each element of a Route in a RequireAuth component.. – Razvan Cretu Nov 06 '21 at 22:20
  • 1
    Please read this https://dev.to/iamandrewluca/private-route-in-react-router-v6-lg5 – Antonio Pantano Nov 06 '21 at 22:27
  • Another option is to separate public and private routes using a common path. For example anything at `/*` is public and anything at `/app/*` is private. These `Route`s will contain parent `element`s that contains a `Routes` component that wraps their respective `Route` components. At the top-level of the private parent component, you'll check for authentication. If it passes, it falls into the private `Routes` switch; otherwise, you can redirect/show an overlay. – Matt Carlotta Nov 06 '21 at 22:32

2 Answers2

5

You cannot compose Routes in React Router v6. Instead, create the Route at the same level as the others, and use your PrivateRoute component inside the element prop. Example (source):

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

function App() {
  return (
    <Routes>
      <Route path="/public" element={<PublicPage />} />
      <Route
        path="/protected"
        element={
          // Good! Do your composition here instead of wrapping <Route>.
          // This is really just inverting the wrapping, but it's a lot
          // more clear which components expect which props.
          <RequireAuth redirectTo="/login">
            <ProtectedPage />
          </RequireAuth>
        }
      />
    </Routes>
  );
}

function RequireAuth({ children, redirectTo }) {
  let isAuthenticated = getAuth();
  return isAuthenticated ? children : <Navigate to={redirectTo} />;
}
Mbrevda
  • 2,888
  • 2
  • 27
  • 35
0

Routing in React V6

  1. Used for navigation in case of multiple pages in a website. We need not to re-render the whole website to navigate to a different page everytime , making a fetch request to a server.
  2. Whole javascript is fecthed at once and then managed by react-router-dom a third party lib for navigation.
   //npm install react-router-dom
   
   <BrowserRouter>
     <Routes>
       <Route path='' element='' exact> //exact is used to load only the specified matched path
       <Route path='' element=''>
        .
        . 
     </Routes>
   </BrowserRouter>
  1. Redirecting :- To redirect a path to a prexisting Path.
        import { Routes,Routes,Navigate } from 'react-router-dom'
        <Routes>
           <Route path='/learn' element={<Learn/>}/>
           <Route path='/learn-apps' element={<Navigate replace to="/learn"/>}/>
        </Routes>     
    
  2. Extracting Parameters from a Route Path :-
            //define a path like this
            <Route path=":courseid" element={<CourseId/>}/>
    
            //In the component use react router hook 
            function CourseId(){
              let {courseid} = useParams();
              return (
                <div>
                  <h1>Your Course Id is : {courseid}</h1>
                </div>
              );
            }
    
    
  3. Carrying Information from route to another route.
    • for this functionality we have to use two hooks i.e. useNavigate,useLocation
    • Lets say we carrying information from a courseId component to a Dashboard ,henceforth the route is changed, so to pass away some info :-
    • Here we are passing a object containing price whenever a user click a button on the courseId component to new Route i.e. dashboard
    • 
         function CourseId(){
           //useNavigate is imported from react-router-dom
           let navigate = useNavigate();
           let {courseid} = useParams();
           return (
               <div>
                 <h1>Your Course Id is : {courseid} </h1>
                 <button
                   onClick={() => {
                     navigate("/dashboard",{ state: {
                       price : "399"
                     } });
                   }}
                 >Pass information</button>
               </div>
             );
           }
      
           function Dashboard(){
               const location = useLocation();
               return(
                 <div>
                   <h1>Info that I got here is {location.state.price} </h1>
                 </div>
               );
             }
      
      • Another simple way of doing is it with using Links
      • 
           //Route intial
           <Link to="/dashboard" state={"DJANGO"}>Dashboard</Link>
        
           //Route final
           const location = useLocation();
           <h1>Info that I got here is {location.state} </h1>
        

Sources : Youtube