Hola chicos tengo un problema. Cuando entro en "tablero", que es una ruta privada, me redirige primero a "iniciar sesión" y luego al tablero. Verdadero y Falso están jugando juntos. ¿Cómo puedo solucionarlo para que no me redirija a iniciar sesión y luego al tablero?
ejemplo de vídeo: https://cdn.aboutluc.xyz/images/rc64kb6af92sswn3r4mv.mp4
código:
import React, { useState, useEffect } from "react" import { toast } from "react-toastify" import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom" import { Login, Register, Dashboard, } from "./Pages" import { Navbar } from "./Components" import './App.css' import "react-toastify/dist/ReactToastify.css" import 'bootstrap/dist/css/bootstrap.min.css' toast.configure() const App = () => { const [ isAuthenticated, setIsAuthenticated ] = useState() const setAuth = (boolean) => { setIsAuthenticated(boolean) } const isAuth = async () => { try { const res = await fetch("http://localhost:5000/api/auth/verify", { headers: { JwtToken: localStorage.JwtToken } }); const parseRes = await res.json(); parseRes === true ? setIsAuthenticated(true) : setIsAuthenticated(false); } catch (error) { console.error(error) } } useEffect(() => { isAuth() }, []) return ( <> <Router> <Navbar setAuth={setAuth} isAuthenticated={isAuthenticated} /> <Routes> <Route exact path="/login" element={ isAuthenticated ? ( <Navigate replace={true} to="/dashboard" /> ) : ( <Login setAuth={setAuth} /> ) } /> <Route exact path="/register" element={ isAuthenticated ? ( <Navigate replace={true} to="/dashboard" /> ) : ( <Register setAuth={setAuth} /> ) } /> <Route exact path="/dashboard" element={ isAuthenticated ? ( <Dashboard setAuth={setAuth} /> ) : ( <Navigate replace={true} to="/login" /> ) } /> </Routes> </Router> </> ) } export default App
El posible problema que veo es la "brecha" en el renderizado inicial donde el estado isAuthenticated
no está definido y la devolución de llamada del useEffect
para establecer ese estado aún no se ha ejecutado. Si intenta acceder directamente a una ruta protegida, independientemente del estado de autenticación real , el código lo rebotará a la ruta de inicio de sesión.
Para esto, normalmente desea usar el "tercer" estado indeterminado para "esperar" ya sea redirigiendo a la autenticación o permitiendo el acceso al componente protegido hasta que se confirme el estado de autenticación.
Abstraer el estado de autenticación en componentes de diseño de autenticación.
const AuthLayout = ({ isAuthenticated }) => { if (isAuthenticated === undefined) return null; // or loading spinner, etc... return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />; }; const AnonymousLayout = ({ isAuthenticated, to }) => { if (isAuthenticated === undefined) return null; // or loading spinner, etc... return isAuthenticated ? <Navigate to={to} replace /> : <Outlet />; };
Utilice los diseños para vigilar/proteger rutas específicas.
<Routes> <Route element={( <AnonymousLayout isAuthenticated={isAuthenticated} to="/dashboard" /> )} > <Route path="/login" element={<Login setAuth={setAuth} />} /> <Route path="/register" element={<Register setAuth={setAuth} />} /> </Route> <Route element={<AuthLayout isAuthenticated={isAuthenticated} />}> <Route path="/dashboard" element={<Dashboard setAuth={setAuth} />} /> </Route> </Routes>
Nota: solo llama a isAuth
cuando se monta el componente de la App
. Es posible que desee llamar a esta función o validar su token de autenticación un poco más a menudo que esto. Pasar isAuth
a los envoltorios de ruta e invocar también en un useEffect
probablemente no sea una idea terrible.