skip to Main Content

I have created routes for page navigation in React JS, now I want to make some of them protected, like I want some them to be accessible only when user Logged In.

const [isLoggedIn, setIsLoggedIn] = useState(false);

useEffect(() => {
  const token = localStorage.getItem("token");
  setIsLoggedIn(!!token);
}, []);

<Route path='/login' element={<Login />} />
<Route path='/signup' element={<SignUp />} />
<Route path='/casting/calls/creation' element={isLoggedIn ? <CastingCallsCreation /> : <Navigate to='/login' />} />
<Route path='/user/film/booth' element={isLoggedIn ? <UserFilmPitchingBooth />: <Navigate to='/login' />} />

here is how I have tried, but cause problem like when I try to navigate to /casting/calls/creation after login successful in login API call, then navigation does not work, it gives successful message for login but does not navigate to that page.

4

Answers


  1. You can achieve that functionality like this

    const [isLoggedIn, setIsLoggedIn] = useState(localStorage.getItem('token') !== null);
    
    useEffect(() => {
      setIsLoggedIn(localStorage.getItem('token') !== null);
    }, []);
    
    return (
      <BrowserRouter>
        {isLoggedIn?
          <Routes>
            <Route path='/casting/calls/creation' element={<CastingCallsCreation />} />
            <Route path='/user/film/booth' element={<UserFilmPitchingBooth />} />
          </Routes>
          :
          <Routes>
            <Route path='/login' element={<Login />} />
            <Route path='/signup' element={<SignUp />} />
          </Routes>
        }
      </BrowserRouter>
    );

    then write refresh code after success the api call like this

    window.location.reload();
    Login or Signup to reply.
  2. You can create an AuthGuard component and wrap your protected layout or route with it:

    import { RouterPaths } from 'config/constant';
    import useLoggedIn from 'hooks/useLoggedIn';
    import { ReactNode } from 'react';
    import { Navigate } from 'react-router-dom';
    
    function AuthGuard(props: Props) {
      const { children } = props;
    
      const isLoggedIn = useLoggedIn();
    
      if (!isLoggedIn) {
        return <Navigate to={RouterPaths.AuthPaths.loginPath} replace />;
      }
    
      return <>{children}</>;
    }
    
    export default AuthGuard;
    
    Login or Signup to reply.
  3. You can try this

    
    // App.js
    import { useState } from 'react';
    import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
    import Login from './Login';
    import SignUp from './SignUp';
    import CastingCallsCreation from './CastingCallsCreation';
    import UserFilmPitchingBooth from './UserFilmPitchingBooth';
    
    const App = () => {
      const [isLoggedIn, setIsLoggedIn] = useState(false);
    
      const handleLogin = () => {
        const token = localStorage.getItem("token");
        setIsLoggedIn(!!token);
      };
    
      return (
        <Router>
          <Routes>
            <Route path='/login' element={<Login onLogin={handleLogin} />} />
            <Route path='/signup' element={<SignUp />} />
            <PrivateRoute path='/casting/calls/creation' isLoggedIn={isLoggedIn} element={<CastingCallsCreation />} />
            <PrivateRoute path='/user/film/booth' isLoggedIn={isLoggedIn} element={<UserFilmPitchingBooth />} />
          </Routes>
        </Router>
      );
    };
    
    const PrivateRoute = ({ isLoggedIn, element, ...rest }) => {
      return (
        <Route
          {...rest}
          element={isLoggedIn ? element : <Navigate to='/login' />}
        />
      );
    };
    
    export default App;
    
    Login or Signup to reply.
  4. The existing answers are fine, as far as they go. But there’s a crucial thing they leave out, and this is too long for a comment:

    Never Trust The Client

    Anybody can open up the browser dev tools and modify anything. Somebody could conceivably run your code in something that isn’t even a browser (much like we do ourselves with RTL and JSDOM) where they have full control over the value of variables.

    The code in the existing answers is fine to help you not make a mistake and communicate to somebody reading the code what routes require authentication/authorization, but do not add any actual security. You must pass authentication credentials with every request (typically tokens that you generate and verify on the server) and assume that any code or data sent to the page is visible to the user (don’t count on your client-side code to prevent unauthorized viewing of data)!

    If you are working solely on the front end (e.g. you work at a big company with dedicated teams/devs for different parts of the stack), then it’s somebody else’s job to deal with this part and you should make sure that your implementation piggy-backs on whatever they already have in place.

    If you’re just learning, then make sure you don’t fall into this extremely common pitfall! It might be a good chance to learn a little server-side development as well.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search