Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

2.7K
Visualizações
Protected route with react router v6

What is correct way to write a ProtectedRoute with new version 6 of react-router? I wrote this one, but it's not a route

const PrivateRoute = ({ component: Component, ...props }) => {   
  if (!Component) return null;

  return props.isAuthenticated
    ? <Component />
    : <Navigate to={props.redirectLink} /> }

export default PrivateRoute;
over 4 years ago · Santiago Trujillo
12 Respostas
Responde à pergunta

0

You would need to write a small wrapper and use Navigate component to redirect. Also you need to render a route

const Container = ({Component, redirectLink, isAuthenticated, ...props}) => {
  if(!isAuthenticated) {
       return <Navigate to={redirectLink} />;
   }
   
   return <Component {...props} />
}
const PrivateRoute = ({ component: Component, redirectLink, isAuthenticated, path, ...props }) => {   

  return (
    <Route
        path={path}
        element={<Container redirectLink={redirectLink} isAuthenticate={isAuthenticated} Component={Component} />}
    />
)

export default PrivateRoute;

You can find the migration guidelines here on the github docs

over 4 years ago · Santiago Trujillo Relatório

0

Here is my working example for implementing private routes by using useRoutes.

App.js

import routes from './routes';
import { useRoutes } from 'react-router-dom';

function App() {
  const { isLoggedIn } = useSelector((state) => state.auth);

  const routing = useRoutes(routes(isLoggedIn));

  return (
    <>
      {routing}
    </>
  );
}

routes.js

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

const routes = (isLoggedIn) => [
  {
    path: '/app',
    element: isLoggedIn ? <DashboardLayout /> : <Navigate to="/login" />,
    children: [
      { path: '/dashboard', element: <Dashboard /> },
      { path: '/account', element: <Account /> },
      { path: '/', element: <Navigate to="/app/dashboard" /> },
      {
        path: 'member',
        element: <Outlet />,
        children: [
          { path: '/', element: <MemberGrid /> },
          { path: '/add', element: <AddMember /> },
        ],
      },
    ],
  },
  {
    path: '/',
    element: !isLoggedIn ? <MainLayout /> : <Navigate to="/app/dashboard" />,
    children: [
      { path: 'login', element: <Login /> },
      { path: '/', element: <Navigate to="/login" /> },
    ],
  },
];

export default routes;
over 4 years ago · Santiago Trujillo Relatório

0

Here is a working example.

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

const PrivateRoute = ({ component: Component, redirectTo, isAuth, path, ...props }) => {
    if(!isAuth) {
        return <Navigate to={redirectTo} />;
    }
    return <Route path={path} element={<Component />} />
};

export default PrivateRoute;

Usage:

<Routes>
     <Route path="app" element={<DashboardLayout />}>
         <PrivateRoute isAuth={true} path="account" component={AccountView}  redirectTo='/login'/>
     </Route>
 </Routes>
over 4 years ago · Santiago Trujillo Relatório

0

I took this example from react-router-dom: https://github.com/remix-run/react-router/blob/main/examples/auth/README.md

Then modify into this https://stackblitz.com/edit/github-5kknft?file=src%2FApp.tsx

export default function App() {
  return (
    <AuthProvider>
      <Routes>
        <Route element={<Layout />}>
          <Route path="/" element={<PublicPage />} />
          <Route path="/public" element={<PublicPage />} />
          <Route path="/login" element={<LoginPage />} />
          <Route element={<RequireAuth />}>
            <Route path="/protected" element={<ProtectedPage />} />
            <Route path="/dashboard" element={<Dashboard />} />
          </Route>
        </Route>
        <Route path="*" element={<NotFound />} />
      </Routes>
    </AuthProvider>
  );
}
function RequireAuth() {
  let auth = useAuth();
  let location = useLocation();

  if (!auth.user) {
    // Redirect them to the /login page, but save the current location they were
    // trying to go to when they were redirected. This allows us to send them
    // along to that page after they login, which is a nicer user experience
    // than dropping them off on the home page.
    return <Navigate to="/login" state={{ from: location }} />;
  }

  return <Outlet />;
}

over 4 years ago · Santiago Trujillo Relatório

0

Here is an official guideline from React Router documentation.

Instead of creating wrappers for your <Route> elements to get the functionality you need, you should do all your own composition in the <Route element> prop.

Taking the example from above, if you wanted to protect certain routes from non-authenticated users in React Router v6, you could do something like this:

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} />;
}

Notice how in this example the RequireAuth component doesn't expect any of <Route>'s props. This is because it isn't trying to act like a <Route>. Instead, it's just being rendered inside a <Route>.

over 4 years ago · Santiago Trujillo Relatório

0

Here's a slightly more TypeScript friendly implementation that reuses RouteProps from react-router v6:

import React from 'react';
import { RouteProps } from 'react-router';
import { Route, Navigate } from 'react-router-dom';
import { useAuthState } from '../../contexts';

export interface PrivateRouteProps extends RouteProps {
  redirectPath: string;
}

export const PrivateRoute = ({ redirectPath, ...props }: PrivateRouteProps) => {
  const { user } = useAuthState();
  if (!user) {
    return <Navigate to={redirectPath} />;
  }
  return <Route {...props} />;
};

useAuthState is a hook that is able to retrieve the user if one is logged in.

This is how I use it:

<Routes>
  <Route path="/" element={<Home />} />
  <PrivateRoute path="/admin" redirectPath="/signin" element={<Admin />} />
  <Route path="*" element={<NotFound />} />
</Routes>
over 4 years ago · Santiago Trujillo Relatório

0

All good options. You can also simply render different route handling based on auth state (or any other state). You don't have to use the raw Javascript object method.

Don't forget you can use an immediately invoked anonymous inner function (() => COMPONENT)() to dynamically decide what component handles a particular <Route/>.

The examples may not yet be in the preliminary documentation for v6 because handling private <Route/>s is actually surprisingly simple.

E.g.

<Routes>
      {state.authed ?
        // Wait until we have the current user...
        currentUser ?
          <Route
            path='/'
            element={(() => {
              // Show a "no access" message if the user is NOT an App Admin doesn't have access to any schools at all (which includes not having access to anything INSIDE any school either)
              if (!currentUser.appAdministrator && currentUser.schoolIds?.length === 0) return <AdminNoAccess />
              return <Outlet />
            })()}
          >
            <Route
              path='/'
              element={(() => {
                // If the user is a super user, we return the <SuperAdmin /> component, which renders some of its own routes/nav.
                if (currentUser.appAdministrator) return <SuperAdmin />
                return <Outlet />
              })()}
            >
              <Route
                path='schools'
                element={(() => {
                  if (currentUser.schoolIds?.length === 1) {
                    return <Navigate to={`schools/schoolId`} />
                  } else {
                    return <AdminSchools />
                  }
                })()}
              />

              <Route path='users' children={<Users />} />
            </Route>

            <Route path={`schools/:schoolId`} element={<AdminSchool />} />

            <Route path='*' element={<Navigate to='schools' />} />
          </Route>
          :
          null
        :
        <>
          <Route path='login' element={<Login />} />
          <Route path='signup' element={<Signup />} />
          <Route path='forgot-password' element={<ForgotPassword />} />
          <Route path='reset-password' element={<ResetPassword />} />

          <Route path='*' element={<Navigate to='login' />} />
        </>
      }
    </Routes>
over 4 years ago · Santiago Trujillo Relatório

0

I tried to use all the above stated ways but don't know why nothing worked for me. Finally i solved it and here is my solution to the same:

First make one file of name AdminRoute.js in "routes" folder somewhere in src.

import { Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Navigate } from "react-router-dom";
import { currentAdmin } from "../../functions/auth";
import LoadingToRedirect from "./LoadingToRedirect";

const AdminRoute = ({ children }) => {
  const { user } = useSelector((state) => ({
    ...state,
  }));
  const [ok, setOk] = useState(false);

  useEffect(() => {
    if (user && user.token) {
      currentAdmin(user.token)
        .then((res) => {
          console.log("CURRENT ADMIN RES", res);
          setOk(true);
        })
        .catch((err) => {
          console.log("ADMIN ROUTE ERR", err);
          setOk(false);
        });
    }
  }, [user]);
  return ok ? children : <LoadingToRedirect />;
};

export default AdminRoute;

Here you can have your own logic to decide when will user e redirected and when he will not.Like in my case i'm Checking if role of user is admin or not by making one api call.

Then make one LoadingToRedirect.js file in the same "routes" folder.

import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";

const LoadingToRedirect = () => {
  const [count, setCount] = useState(5);
  let navigate = useNavigate();

  useEffect(() => {
    const interval = setInterval(() => {
      setCount((currentCount) => --currentCount);
    }, 1000);
    // redirect once count is equal to 0
    count === 0 && navigate("/");
    // cleanup
    return () => clearInterval(interval);
  }, [count, navigate]);

  return (
    <div className="container p-5 text-center">
      <p>Redirecting you in {count} seconds</p>
    </div>
  );
};

export default LoadingToRedirect;

Now set up your App.js in your app.js:

Here when you go to '/check' url, the private route functionalities will come in action and it will check if the user is 'admin' or not.Here is the page which is to be protected and it acts as 'children' to

<Routes>
          <Route
            path="/check"
            element={
              <AdminRoute>
                <Check />
              </AdminRoute>
            }
          />

     
          <Route path="*" element={<NotFound />} />
        </Routes>

That's it You are ready to go. Cheers!!

over 4 years ago · Santiago Trujillo Relatório

0

This is the structure for the BrowserRouter as Router:

const AppRouter = () => {
  return (
    <Router>
      <Layout>
        <Routes>
          <Route exact path="" element={<Home />} />
          <Route exact path="login" element={<Login />} />
          <Route exact path="register" element={<Register />} />

          // These are the Private Components
          <Route
            exact
            path="/account"
            element={
              <PrivateRoute>
                <Account />
              </PrivateRoute>
            }
          />

          <Route
            exact
            path="/quizzes"
            element={
              <PrivateRoute>
                <Quizzes />
              </PrivateRoute>
            }
          />

          <Route
            exact
            path="/quizz/:quizzid"
            element={
              <PrivateRoute>
                <Quizz />
              </PrivateRoute>
            }
          />

          <Route
            exact
            path="/admin/users"
            element={
              <PrivateRoute>
                <Users />
              </PrivateRoute>
            }
          />
          <Route exact path="*" element={<NotFound />} />
        </Routes>
      </Layout>
    </Router>
  );
};

This is the PrivateRoute:

import { Navigate } from "react-router-dom";
import { useAuth } from "../auth/useAuth";

function PrivateRoute({ children }) {
  const auth = useAuth();
  return auth.user ? children : <Navigate to="/login" />;
}

export default PrivateRoute;
over 4 years ago · Santiago Trujillo Relatório

0

You could use auth-react-router package https://www.npmjs.com/package/auth-react-router

It provides a really simple API to define your routes and few more configurations (like redirect routes for authorized and unauthorized routes, fallback component for each of the routes)

usage:

  1. define routes
// routes.tsx

import React from 'react';
import { IRoutesConfig } from 'auth-react-router';
import LoginPage from '../pages/LoginPage.tsx';

// public lazy loaded pages
const LazyPublicPage = React.lazy(() => import('../pages/PublicPage.tsx'));

// private lazy loaded pages
const LazyPrivatePage = React.lazy(() => import('../pages/PrivatePage.tsx'));
const LazyProfilePage = React.lazy(() => import('../pages/ProfilePage.tsx'));


export const routes: IRoutesConfig = {
  publicRedirectRoute: '/profile', // redirect to `/profile` when authorized is trying to access public routes
  privateRedirectRoute: '/login', // redirect to `/login` when unauthorized user access a private route
  defaultFallback: <MyCustomSpinner />,
  public: [
    {
      path: '/public',
      component: <LazyPublicPage />,
    },
    {
      path: '/login',
      component: <LoginPage />,
    },
  ],
  private: [
    {
      path: '/private',
      component: <LazyPrivatePage />,
    },
    {
      path: '/profile',
      component: <LazyProfilePage />
    },
  ],
  common: [
    {
      path: '/',
      component: <p>common</p>,
    },
    {
      path: '*',
      component: <p>page not found 404</p>,
    },
  ],
};
  1. link them to your application
import { AppRouter, Routes } from 'auth-react-router';
import { BrowserRouter } from 'react-router-dom';
import { routes } from './routes';

export const App = () => {
  const { isAuth } = useAuthProvider();
  return (
    <BrowserRouter>
      <AppRouter isAuth={isAuth} routes={routes}>
        {/* Wrap `Routes` component into a Layout component or add Header */}
        <Routes />
      </AppRouter>
    </BrowserRouter>
  );
};
over 4 years ago · Santiago Trujillo Relatório

0

By using replace attribute we prevent the user to use the Back browser button.

PrivateRoute.js

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

const PrivateRoute = ({ currentUser, children, redirectTo }) => {
  if (!currentUser) return <Navigate to={redirectTo} replace />;

  return children;
};

export default PrivateRoute;

Implementation:

<Routes>
   <Route path='signIn' element={
            <PrivateRoute currentUser={currentUser} redirectTo='/'>
              <SignInAndSignUpPage />
            </PrivateRoute>
          }
        />
<Routes/>
over 4 years ago · Santiago Trujillo Relatório

0

I don't know if this is the right way to do it but you don't actually need a private route component. You can just put all the private routes inside a component and render it conditionally as follows. In the below code, I put all the private routes inside the Private component and all the open routes inside the Public component.

function RootRouter() {

  return (
    <div>
      <Router>
        {isLoggedIn ? <PrivateRouter /> : <PublicRouter />}
      </Router>
    </div>
  );
}

function PrivateRouter(props) {
  return (
    <div>
      <ToastContainer autoClose={3000} hideProgressBar />
      <NavBar />
      <Routes>
        <Route path="/" exact element={<Home />} />
        <Route path="/add" element={<Add />} />
        <Route path="/update/:id" element={<Add />} />
        <Route path="/view/:id" element={<Employee />} />
      </Routes>
    </div>
  );
}

function PublicRouter() {
  return (
    <Routes>
      <Route path="/" element={<Login />} />
    </Routes>
  );
}

You can also use switch cases to allow access based on the role of the user.

Note: you dont have a create a seperate components, you can actually put all the routes in a single component and render it using same conditions.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda