Firebase鉴权场景下PrivateRoute未登录时未跳转到指定登录路由问题
问题原因
你遇到的问题是两个常见的Firebase Auth结合前端路由的典型错误:
- Firebase的登录状态初始化是异步操作,页面刚加载/登出操作刚触发时,
currentUser的初始值会是null,你现有代码没有加加载状态判断,直接用currentUser做路由判定,会出现状态还没更新就渲染了私有路由的情况。 - 登出操作是异步接口,你如果没有等
signOut执行完成就跳转,会出现登出请求还没走完、路由先跳转回根路径,此时Firebase还没更新登录状态,导致私有路由判定异常。
修复方案
1. 重写私有路由逻辑,增加加载状态和登录状态监听
修改PrivateRoute.js代码如下:
import { Navigate } from "react-router-dom"; import { useEffect, useState } from "react"; import { getAuth, onAuthStateChanged } from "firebase/auth"; const PrivateRoute = ({ children }) => { const [currentUser, setCurrentUser] = useState(null); const [loading, setLoading] = useState(true); const auth = getAuth(); useEffect(() => { // 绑定Firebase登录状态监听器,确保拿到的是最新的登录状态 const unSubscribe = onAuthStateChanged(auth, (user) => { setCurrentUser(user); setLoading(false); }); // 组件卸载时解绑监听器避免内存泄漏 return unSubscribe; }, [auth]); // 状态未加载完成时渲染加载占位,不做路由判断也不渲染私有页面 if (loading) return <div>加载中...</div>; // 状态加载完成后再判断是否有权限访问 return currentUser ? children : <Navigate to="/login" replace />; }; export default PrivateRoute;
2. 修改登出逻辑,确保异步操作完成后再跳转
修改登出事件处理代码如下:
import { getAuth, signOut } from "firebase/auth"; import { useNavigate } from "react-router-dom"; const handleLogout = async () => { const auth = getAuth(); const navigate = useNavigate(); try { // 等待登出接口执行完成,Firebase更新登录状态 await signOut(auth); // 显式跳转到登录页 navigate("/login", { replace: true }); } catch (error) { console.error("登出失败:", error); } };
3. 补充空值防护
根路径页面所有使用currentUser属性的地方,都改成可选链写法,比如把currentUser.uid改成currentUser?.uid,避免空值报错。
内容的提问来源于stack exchange,提问作者Spicy Sauce
相关产品推荐
相关产品推荐

