Home > Net >  How to protect routes in React 18?
How to protect routes in React 18?

Time:02-03

I have an admin dashboard and want that only admins are able to see the pages. So I set a condition into my router. When I am logged in, I am able to open every page, but I get the warning:

No routes matched location “/pagename”

Navbar and Sidebar staying in the same position, so that every page opens in a div named ContentWrapper. How can I get rid of this warning?

Code:

 const admin = useAppSelector((state)=>state.auth.user?.isAdmin);
  return (
   
    <Container>
    <Router>
      <Routes>
       <Route path="/" element={<Login/>}/>
      </Routes>
      {admin && 
    <>
      <Navbar/>
      <Wrapper>
        <Sidebar/>
        <ContentWrapper>
          <Routes>
              <Route path="/home" element={<Home/>}/>
              <Route path="/sales" element={<Sales/>}/>
              <Route path="/analytics" element={<Analytics/>}/>
              <Route path="/transactions" element={<Transactions/>}/>
              <Route path="/reports" element={<Reports/>}/>
              <Route path="/mail" element={<Mail/>}/>
              <Route path="/feedback" element={<Feedback/>}/>
              <Route path="/messages" element={<Messages/>}/>
              <Route path="/manage" element={<Manage/>}/>
              <Route path="/user" element={<User/>}/>
              <Route path="/products" element={<Products/>}/>
              <Route path="/productlistChild" element={<ProductlistChild/>}/>
              <Route path="/productlistWomen" element={<ProductlistWomen/>}/>
              <Route path="/productlistMen" element={<ProductlisttMen/>}/>
              <Route path="/productlistSportschuhe" element={<ProductlistSportschuhe/>}/>
              <Route path="/productlistSneaker" element={<ProductlistSneaker/>}/>
              <Route path="/cardImages" element={<CardImages/>}/>
              <Route path="/sneakerImage" element={<SneakerImage/>}/>
              <Route path="/sliderImage" element={<SliderImages/>}/>
              <Route path="/newsletterBackground" element={<NewsletterBackground/>}/>
              <Route path="/descriptionItems" element={<DescriptionItems/>}/>
              </Routes>
          </ContentWrapper>
        </Wrapper>
        </>
        }
      </Router>
    </Container>
  );
}

CodePudding user response:

Did something similar recently

You can create a PrivateRoute Component

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

const PrivateRouteAdmin = ({ isLoggedIn, role }) => {
  return isLoggedIn && role === 'Admin' ? <Outlet /> : <Navigate to="/login" />;
};

export default PrivateRouteAdmin;

and then you can use it in your App.js like this

      <Route element={<PrivateRouteAdmin isLoggedIn={isLoggedIn} role={user?.data?.role} />}>
        <Route element={<DashboardWrapper />}>
          {PublicRoutesAdmin.map((route, index) => {
            return <Route key={index} path={route.path} element={<route.component />} />;
          })}
        </Route>
      </Route>

PublicRoutesAdmin.map has just all the routes in a separate file, nothing fancy.

You can have other public routes pout of the private route component

CodePudding user response:

I would resolve this by creating two groups of routes: Private and Public:

const PublicRoutes = () => (
    <Fragment>
        <Route path="/public/a"><ComponentA /></Route>
        <Route path="/public/b"><ComponentB /></Route>
    </Fragment>
)

const PrivateRoutes = () => (
    <Fragment>
        <Route path="/private/a"><PrivComponentA /></Route>
        <Route path="/private/b"><PrivComponentB /></Route>
    </Fragment>
)

And then have a RootRouter component which conditionally renders either the public or the private routes based on a condition:

const RootRouter = () => {

    return (
        <Router>
            <Routes>
                {admin ? 
                    <Fragment> 
                        <PublicRoutes />
                        <PrivateRoutes />
                    </Fragment> : 
                    <PublicRoutes />
                }
            </Routes>
        </Router>
    )
}

This way, you are rendering the PublicRoutes AND the PrivateRoutes for the admin, but only the PublicRoutes for non-admin users.

  • Related