Search code examples
javascriptreactjsreact-router-dompage-refresh

Always getting redirected to homepage on refresh from any route in app


I am using functional component which provides authentication to the specific routes such as /home using server side authentication and local storage, happening in OnSubmit event of my of login page.

Everything works fine I am getting redirected to homepage after successful login, the problem arises when I refresh the page from any route I am always getting redirected to home page, why is that so?

The problem arises in production as well as in development, anyone please suggest me a way to fix this

My App.js file is

App.js

import React, { useState, useEffect } from 'react';
import Swal from 'sweetalert2';
import {
  BrowserRouter as Router,
  Route,
  Switch,
  Redirect,
} from 'react-router-dom';

import LoginPage from './login/LoginPage';
import HomePage from './home/HomePage';
import Courses from './courses/Courses';
import Profile from './profile/Profile';
import Notes from './notes/Notes';
import Contact from './contact/Contact';
import Students from './students/Students';
import OnlineClass from './onlineClass/OnlineClass';
import NotFound from './notfound/NotFound';
import UpdateClass from './updateData/UpdateClass';
import UpdateNotes from './updateData/UpdateNotes';

const App = () => {
  const [loggedIn, setLoggedIn] = useState(false);

  useEffect(() => {
    const loggedUser = localStorage.getItem('user');
    if (loggedUser) {
      setLoggedIn(true);
    }
  }, []);

  const handleLoggedIn = () => {
    setLoggedIn(true);
  };

  const handleLogout = () => {
    Swal.fire({
      title: 'Are you sure?',
      showDenyButton: true,
      showCancelButton: true,
      confirmButtonText: `Yes`,
      denyButtonText: `No`,
    }).then((result) => {
      if (result.isConfirmed) {
        setLoggedIn(false);
        localStorage.clear();
      } else if (result.isDenied) {
        Swal.fire('Welcome back!', '', 'info');
      }
    });
  };

  return (
    <div>
      <Router>
        <Switch>
          <Route exact strict path='/'>
            {!loggedIn ? (
              <LoginPage handleLoggedIn={handleLoggedIn} />
            ) : (
              <Redirect to='/home' />
            )}
          </Route>
          <Route exact path='/home'>
            <HomePage handleLogout={handleLogout} loggedIn={loggedIn} />
          </Route>
          <Route exact path='/profile'>
            <Profile loggedIn={loggedIn} handleLogout={handleLogout} />
          </Route>
          <Route exact path='/courses'>
            <Courses loggedIn={loggedIn} handleLogout={handleLogout} />
          </Route>
          <Route exact path='/notes'>
            <Notes loggedIn={loggedIn} handleLogout={handleLogout} />
          </Route>
          <Route exact path='/contact'>
            <Contact loggedIn={loggedIn} handleLogout={handleLogout} />
          </Route>
          <Route exact path='/students'>
            <Students loggedIn={loggedIn} handleLogout={handleLogout} />
          </Route>
          <Route exact path='/class'>
            <OnlineClass loggedIn={loggedIn} handleLogout={handleLogout} />
          </Route>

          <Route exact path='/class/update/:id'>
            {!loggedIn ? (
              <LoginPage handleLoggedIn={handleLoggedIn} />
            ) : (
              <UpdateClass />
            )}
          </Route>
          <Route exact path='/notes/update/:id'>
            {!loggedIn ? (
              <LoginPage handleLoggedIn={handleLoggedIn} />
            ) : (
              <UpdateNotes />
            )}
          </Route>
          <Route>
            <NotFound />
          </Route>
        </Switch>
      </Router>
    </div>
  );
};

export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>


Solution

  • The problem is that setLoggedIn(true); is executed after the redirect action:

    You need to check if user has been loaded or not. You can initialize loggedIn to null

    const [loggedIn, setLoggedIn] = useState(null);
    
    useEffect(() => {
        const loggedUser = localStorage.getItem('user');
        setLoggedIn(Boolean(loggedUser));
      }, []);
    

    Then you can ignore render the routes if loggedIn === null

    return (
        <div>
          { loggedIn !== null &&
             <Router>
                ...
             </Router>
          }
    
        </div>
      );