ReactJS ProtectedRoute redirects. Variable rendered twice, false on the first time yet its true in the redux-store

Am trying to implement the ProtectedRoute. But when i pass authentication, meaning am authenticated rightly from the auth API, get my token, i get pushed to the main page without a problem. However, when i type in the browser the URL manually to the protected route, i get redirected to the Login page.

Am storing the isAuthenticated flag in a redux store using redux-toolkit. Check out my code below

ProtectedRoute.jsx

import React, { useState, useEffect } from 'react';
import { Route, Redirect } from "react-router-dom";
import { useSelector } from 'react-redux'

const ProtectedRoute = ( { component: Component, ...rest }) => {

    const isLoggedIn = useSelector(state => state.auth.isAuthenticated);
    const [ isAuthed, setAuthed ] = useState(false);

    useEffect(() => {
        setAuthed(isLoggedIn);
    }, [isLoggedIn]);


    return (
        <Route 
            {...rest}
               render={
                  props => (
                    isAuthed === true
                      ? <Component {...props} />
                      : <Redirect to={{ pathname: '/', state: { from: props.location} }}/>
                )
            }
      />
  )
}

export default ProtectedRoute

The composition of the App.js are as follows

      <Router>
            <Switch>
                <Route exact path="/" component={SignIn} />
                <ProtectedRoute exact path="/main" component={ Dashboard } />
                <Route path="*">
                  <div>404 Not found</div>
                </Route>
            </Switch>
        </Router>

I tried passing this login as a prop from the App.js to the ProtectedRoute but still i cant get the result i want.

What i realized though is that there's double rendering. On the first time, reading the isLoggedIn variable produces a false result and therefore forces a redirect.

1 answer

  • answered 2021-04-14 18:13 Muhammad Hassaan Ather

    Typing URL manually or copying the URL to another tab destroys the OLD state. This happens when we try to get our state from redux Store using useSelector. I solved it by using backend code and providing expiry time for each user logged in and than linked that user with store's State. To check if user's time is expired or not i used npm package Decode and this small code.

     const token = user?.token;  //this user is srored in localstorage
       // JWT..
       if (token) {
         const decodedToken = decode(token);
    
         if (decodedToken.exp * 1000 < new Date().getTime()) logout(i); //here is what you    
                                                                       // need at frontend
       }
       setUser(JSON.parse(localStorage.getItem("profile")));