Pranab V V
Pranab V V

Reputation: 1446

How to apply authguard to routes having multiple components in reactjs

I have routes with single and multiple components.I am using authguard to restrict access to some routes.How can I apply the authguard to the routes having multiple components.

routes.js

import { BrowserRouter as Router,Route} from 'react-router-dom';
import React from 'react';
import { FirstConnectedComponent,SecondConnectedComponent } from './App.js';
import Header  from './components/header.js';
import Footer  from './components/footer.js';
import Login from './components/login.js';
import UserReg from './components/registration.js';
import Home from './components/home';
import requireAuth from './components/authentication';
import PrivateRoute from './components/privateroutes';
const routes=() => (
    <Router>
        <div>
            <Header />
                <Route exact path="/" render={ props =>  <div><FirstConnectedComponent /><SecondConnectedComponent /></div>} />
                <Route path="/login" component={PrivateRoute(Login) } />
                <Route path="/register" component={ UserReg } />
                <Route path="/home" component={ requireAuth(Home)} />
            <Footer />
        </div>
    </Router>

)
export default routes;

In the above code I already applying authguard to routes having single components.But I don't know how to be applied into routes having multiple components.

privateroute

import { connect } from 'react-redux';
import React from 'react';
import { withRouter } from 'react-router';

export default function PrivateRoute(Component) {

  class AuthenticatedComponent extends React.Component {

    componentWillMount() {
        console.log(this.props.loginStatus);
      this.checkAuth();
    }

    checkAuth() {
       if (this.props.loginStatus==1) {
        this.props.history.push(`/home`);
      }
    }

    render() {
      return this.props.loginStatus!=1
        ? <Component { ...this.props } />
        : null;
    }

  }
  function mapStateProps(state)  {
    return {
        loginStatus:state.loginDetails.status
    }   
  }
  return connect(mapStateProps)(withRouter(AuthenticatedComponent));
}

Upvotes: 1

Views: 1871

Answers (2)

GMKHussain
GMKHussain

Reputation: 4671

Solution for v6 newer version of react-router-dom

If useNavigate not working, use useHistory

App.js

import React from 'react'
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import AuthGuard from "./Routes/AuthGuard";

function App() {
  return (
    <div className='App'>
        <Router>
          <Routes>
              <Route path='/' element={<Home />} />
              <Route path='/contact' element={<Contact />} />
              <Route path='/guest-page' element={<AuthGuard isGuest={true}><h1>Guest Page</h1></AuthGuard>} />
              <Route path='/protected-page' element={<AuthGuard requireToken={true}><h1>ProtectedPage</h1></AuthGuard>} />
          </Routes>
        </Router>
    </div>
  );
}

export default App;

AuthGuard.js

import { Route, useNavigate } from "react-router-dom";
import { useLayoutEffect } from "react";

const ProtectedRoute = ({requireToken, guest, children, ...rest}) => {
    
    console.log(requireToken, guest, children, rest); 
    
    const navigate = useNavigate();
    const hasToken = false;

    let hasAccess = (!requireToken || (requireToken && hasToken));
    let navigateTo = '/?login-rquired=true'; 

    if(guest) {
        hasAccess = !hasToken; 
        navigateTo = '/?guest=true';
        console.log("Guest > hasAccess: " + hasAccess)
    }

    if(requireToken){
        console.log("requireToken", requireToken)
    }
    
    useLayoutEffect(()=>{
        if (!hasAccess) {
            console.log("Not allowed");
            navigate(navigateTo);
        }
    },[])

    return (
        <>{ hasAccess ? children : "Login required" }</>
    )
}

export default ProtectedRoute;

Upvotes: 0

Shubham Khatri
Shubham Khatri

Reputation: 281656

Instead of using render prop use the component prop as you have used the same in PrivateRoute and wrap the render function with PrivateRoute HOC like

const routes=() => (
    <Router>
        <div>
            <Header />
                <Route exact path="/" component={PrivateRoute(props =>  <div><FirstConnectedComponent /><SecondConnectedComponent /></div>)} />
                <Route path="/login" component={PrivateRoute(Login) } />
                <Route path="/register" component={ UserReg } />
                <Route path="/home" component={ requireAuth(Home)} />
            <Footer />
        </div>
    </Router>

)

Upvotes: 1

Related Questions