Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Configuring private routes with react-router-dom v6

When the visitor goes to / (home), I want him to be redirected to /connexion" if he is not connected. I created Private routes for that, which works fine. Now, I want to implement the logic that will redirect the user according to if he is connected or not.

I have these routes in App.jsx:

import ProtectedRoutes from './middlewares/ProtectedRoutes';

return (
    <>
      <Routes>
        <Route path="/connexion" element={<Login />} />
        <Route path="/auto-connexion" element={<AutoConnect />} />

        <Route element={<AppLayout />} >
          <Route element={<ProtectedRoutes />}>
            <Route path="/" element={<Home />} />
            <Route path="/logical-entity-selection" element={<LogicalEntitySelection />} />
            <Route path="/produits" element={<Products />} />
            <Route path="/produits/:id" element={<Product />} />
            <Route path="/actualites" element={<Articles />} />
            <Route path="/actualites/id" element={<Article />} />
            <Route path="/mes-parametres" element={<MyAccount />} />
            <Route path="/mes-outils-et-services" element={<MyToolsAndServices />} />
            <Route path='*' element={<Login />} />
          </Route>
        </Route>
      </Routes>
    </>
  );

An this ProtectedRoutes.tsx :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import { useEffect, useState } from "react"
import { Navigate, Outlet } from "react-router-dom"
import jwt_decode from "jwt-decode"
import instance from "../api/axios"

export default function ProtectedRoutes() {
    const [isLoggedIn, setIsLoggedIn] = useState(Boolean)

    const token = window.localStorage.getItem("token") || ''
    const decodedToken: any = jwt_decode(token)
    const uuid = decodedToken.uuid

    const isAuth = async () => {
        await instance.get(`/users/${uuid}`, {
            headers: {
                'Authorization': `Bearer ${token}`
            }
        }).then((res) => {
            console.log(res)
            if (res.status === 200) setIsLoggedIn(true)
            return setIsLoggedIn(false)
        })
    }

    useEffect(() => {
        isAuth()
    }, [isLoggedIn])

    return isLoggedIn ? <Outlet /> : <Navigate to={'/connexion'} />
}

The problem is that with this code, React render the Login Component because it returns always false, even if I have a status 200 after my request and set the new state to true.

How can I make my request FIRST, then set the new state for isLoggedIn, then decide to render Login component or Home component ?

I hope I made it clear. Don’t hesitate to question me if not. Any help on this ?

>Solution :

You would need a loading state in addition to what you have to make it work correctly, I called it isChecking. Also the below block of code that you have should be changed, because you are setting isLoggedIn to true and right after to false.

 if (res.status === 200) setIsLoggedIn(true)
 return setIsLoggedIn(false)

Solution:

import { useEffect, useState } from "react"
import { Navigate, Outlet } from "react-router-dom"
import jwt_decode from "jwt-decode"
import instance from "../api/axios"

export default function ProtectedRoutes() {
    const [isLoggedIn, setIsLoggedIn] = useState(false)
    const [isChecking, setIsChecking] = useState(true)
    const token = window.localStorage.getItem("token") || ''
    const decodedToken: any = jwt_decode(token)
    const uuid = decodedToken.uuid

    const isAuth = async () => {
        await instance.get(`/users/${uuid}`, {
            headers: {
                'Authorization': `Bearer ${token}`
            }
        }).then((res) => {
            console.log(res)
            if (res.status === 200) setIsLoggedIn(true)
            setIsChecking(false);
            return;
        })
    }

    useEffect(() => {
        isAuth()
    }, [isLoggedIn])

    if(isChecking) return <p>Checking....</p>

    return isLoggedIn ? <Outlet /> : <Navigate to={'/connexion'} />
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading