0

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;
Moammer
  • 139
  • 1
  • 2
  • 11

1 Answers1

0

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>
  );
}
SlothOverlord
  • 1,655
  • 1
  • 6
  • 16
  • I'm sorry but I didn't manage to put this together to work for me – Moammer Mar 11 '22 at 14:00
  • Are there any errors or is route not rendered? – SlothOverlord Mar 11 '22 at 14:10
  • I'm a beginner in React-Routes. I understand the changes of Redirect to Navigate and the change in the Routes but I just need details of how use your recommended code (const PrivateOutlet). should I replaced with my code in PrivateRoute and change file name? – Moammer Mar 11 '22 at 14:15
  • I edited my answer. Just make sure that auth is passed correctly and it should work. – SlothOverlord Mar 11 '22 at 14:36
  • Now once I try your code I get redirected to login page but once I login I can't view the about page as it directs me to Welcome page because the logic in login page (if isAuthenticated Navigate to Welcome page). why I can't view about page? – Moammer Mar 11 '22 at 19:36
  • I updated my question after removing unnecessary items but still. I only get directed to the login page – Moammer Mar 11 '22 at 19:56
  • You need to make sure that the user is either logged in or not. For example, If you render the route while fetching auth data, it will redirect you to /logout because it thinks that you are logged out, but in reality it is still undefined. The solution to this is to NOT render Router component while you are checking for credentials. If auth is undefined, render loading component, if it is defined and filled, render outlet, if it is defined but empty, render logout – SlothOverlord Mar 17 '22 at 09:29
  • SlothOverlord, Thanks for your reply. The problem is solved here; https://stackoverflow.com/questions/71444130/privateoutlet-js-doesnt-render-page-after-authentication but now I can't login unless I go through the about page(PrivateOutlet). all updates are on the page I just added. Many Thanks! – Moammer Mar 17 '22 at 14:27