PrivateRoute isn't working, react route changes v5 - v6.2

780 Views Asked by At

My code isn't working due to the changes of React route from v5 to v6.2. could you please help me change PrivateRoute.js details to match the requirements of v6.2?

PrivateRoute.js; strong text


import React, { Component } from 'react';
import { Route, Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

const PrivateRoute = ({ component: Component, auth: { isAuthenticated, loading }, ...rest }) => (
    <Route
        {...rest}
        render={props => !isAuthenticated && !loading ? (<Redirect to='/login' />) : (<Component {...props} />)}
    />
);

PrivateRoute.propTypes = {
    auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
    auth: state.auth
});

export default connect(mapStateToProps)(PrivateRoute);

Some changes I figured out : Redirect to Navigate. Also, I changed my routes in App.js to ;

function App() {
  return (
    <Provider store={store}>
      <Router>
        <Layout>
          <Routes>
            <Route path='/' element={<WelcomePage/>} />
            <Route path='/home' element={<Home/>} />

            <Route element={<PrivateRoute/>}>
              <Route path='/about' element={<About/>} />
            </Route>

            <Route path='*' element={<NotFound/>} />
          </Routes>
        </Layout>
      </Router>
    </Provider>
  );
}

export default App;

the below is edited but still I doesn't render the about page. instead I get redirected to login;


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

const PrivateOutlet = ({isAuthenticated}) => {
    if(isAuthenticated ) { 
     return  <Outlet /> 
    }
   else {
    return <Navigate to='login'/> //Go to login
}};


export default PrivateOutlet;
1

There are 1 best solutions below

8
SlothOverlord On

You need to render the Route component first, then check for auth and render the outlet inside of it. Outlet is the nested route. Redirect was renamed to Navigate, and you no longer have to pass any props to your routes.

const PrivateOutlet = () => {
   if(isAuthenticated && loading) {
      return <Outlet />
    }
   else {
    return <Navigate to='login'/>
}
};

//...

 <Route  path='/about' element={<PrivateOutlet/>}>
      <Route index element={<About/>} /> //Rendered as outlet component
      <Route path='me' element={<About/>} /> //Rendered as outlet component
  </Route>

EDIT: full code

PrivateOutlet.js

import React, { Component } from 'react';
import { Route, Outlet, Navigate } from 'react-router-dom';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

//Never used redux or proptypes, so make sure auth is passed correctly
const PrivateOutlet = ({auth}) => {
    if(auth.isAuthenticated && auth.loading) { //Check for auth here
     return  <Outlet /> //Render the current page
    }
   else {
    return <Navigate to='login'/> //Go to login
}};

PrivateRoute.propTypes = {
    auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
    auth: state.auth
});

export default connect(mapStateToProps)(PrivateRoute);

App.js

function App() {
  return (
    <Provider store={store}>
      <Router>
        <Layout>
          <Routes>
            <Route path='/' element={<WelcomePage/>} />
            <Route path='/home' element={<Home/>} />

            //If this doesn't work, try the other one
            <Route element={<PrivateOutlet/>}>
              <Route path='/about' element={<About/>} />
            </Route>

            <Route path='/about' element={<PrivateOutlet/>}>
              <Route index element={<About/>} /> //This will get rendered as Outlet
              //<Route path='me' element={<About/>} /> //Add more nested routes like this. without "/"
            </Route>

            <Route path='*' element={<NotFound/>} />
          </Routes>
        </Layout>
      </Router>
    </Provider>
  );
}