Estoy usando Firebase v9 y react-router v6. No he usado v6, así que esto fue bastante confuso. ¿Cómo puedo hacer que el usuario invitado solo pueda acceder a la página de inicio de sesión? Solo los usuarios que iniciaron sesión pueden acceder a la página de inicio y otras páginas.
Cada vez que vuelva a cargar cualquier página, se mostrará esto en la consola, pero seguirá dirigiendo al usuario a la página correcta:
No hay rutas que coincidan con la ubicación "/ubicación de la página"
¿Cómo puedo usar una ruta privada para la página de perfil?
//custom hook export function useAuth() { const [currentUser, setCurrentUser] = useState(); useEffect(() => { const unsub = onAuthStateChanged(auth, (user) => setCurrentUser(user)); return unsub; }, []); return currentUser; }Aplicación.js
import { auth, useAuth } from "./Firebase/utils"; import { onAuthStateChanged } from "firebase/auth"; function App() { const currentUser = useAuth(); const user = auth.currentUser; const navigate = useNavigate(); console.log(currentUser?.email); useEffect(() => { onAuthStateChanged(auth, (user) => { if (user) { // User is signed in, see docs for a list of available properties // https://firebase.google.com/docs/reference/js/firebase.User const uid = user.uid; console.log(uid); navigate("/Home"); // ... } else { // User is signed out // ... navigate("/"); } }); }, []); return ( <div> <div> <Routes> {currentUser ? ( <> //If i do it this way and I'll go the profile page and reload it, it will always go to back to the Homepage. <Route path="/Home" element={<Home />} /> <Route path="/Profile" element={<ProfilePage />} /> </> ) : ( <> <Route path="/" element={ <LogInPage /> } /> </> )} </Routes> </div> </div> ); } export default App; Esto es lo que muestra el console.log(user) :
Archivo paquete.json:
El problema principal es que el valor de currentUser es inicialmente falso
const [currentUser, setCurrentUser] = useState(); y está tomando una decisión de navegación sobre el estado de autenticación no confirmado en la App
<Routes> {currentUser ? ( <> // If i do it this way and I'll go the profile page and reload it, // it will always go to back to the Homepage. <Route path="/Home" element={<Home />} /> <Route path="/Profile" element={<ProfilePage />} /> </> ) : ( <> <Route path="/" element={<LogInPage />} /> </> )} </Routes> Al actualizar la página, el estado de currentUser se restablece, no está definido, es decir, es falso, y solo se representa la ruta "/" .
En react-router-dom es una práctica común abstraer la protección de ruta en un componente especializado de "ruta protegida". También querrá manejar condicionalmente el estado indeterminado hasta que su verificación de autenticación de Firebase haya tenido la oportunidad de confirmar un estado de autenticación y actualizar el estado currentUser del usuario.
Ejemplo:
export function useAuth() { const [currentUser, setCurrentUser] = useState({}); // <-- provide object to destructure from useEffect(() => { const unsub = onAuthStateChanged(auth, (user) => setCurrentUser(user)); return unsub; }, []); return currentUser; } AuthWrapper: utiliza el gancho useAuth para verificar el estado de autenticación del usuario. Si currentUser no está definido, condicionalmente devuelve un null temprano o algún otro indicador de carga. Una vez que el estado del currentUser se completa/define, el componente representa condicionalmente un Outlet para los componentes Route anidados/envueltos que desea proteger, o el componente Navigate para redirigir a su ruta de autenticación.
import { Navigate, Outlet, useLocation } from 'react-router-dom'; const AuthWrapper = () => { const location = useLocation(); const { currentUser } = useAuth(); if (currentUser === undefined) return null; // <-- or loading spinner, etc... return currentUser ? <Outlet /> : <Navigate to="/" replace state={{ from: location }} />; }; Aplicación: representa incondicionalmente todas las rutas, envolviendo las rutas de Home y Profile en la ruta de diseño AuthWrapper .
function App() { return ( <div> <div> <Routes> <Route element={<AuthWrapper />}> <Route path="/Home" element={<Home />} /> <Route path="/Profile" element={<ProfilePage />} /> </Route> <Route path="/" element={<LogInPage />} /> </Routes> </div> </div> ); }