Firebase+React无密码认证完成后PrivateRoute仍跳转登录页问题
问题原因&解决方案
1. 认证初始化异步导致路由提前跳转
Firebase的持久化登录状态恢复是异步操作,你当前AuthProvider初始化时isAuth默认设为false,在onAuthStateChanged回调触发、拿到真实登录状态前,PrivateRoute已经判定未登录,直接触发重定向回到登录页。
修改useAuthContext.js,新增加载状态避免提前跳转:
export const AuthDataContext = createContext(null); const AuthProvider = (props) => { const [isAuth, setIsAuth] = useState(false); // 新增认证状态加载标识 const [authLoading, setAuthLoading] = useState(true); useEffect(() => { const unsubscribe = firebase.auth().onAuthStateChanged((user) => { setIsAuth(!!user); // 状态确认后关闭加载 setAuthLoading(false); }); // 组件卸载时取消订阅防止内存泄漏 return () => unsubscribe(); }, []); const onLogin = () => setIsAuth(true); const onLogout = () => { firebase.auth().signOut(); setIsAuth(false); }; // 把加载状态同步到上下文 return <AuthDataContext.Provider value={{ isAuth, authLoading, onLogin, onLogout }} {...props} />; }; export default AuthProvider; export const useAuthDataContext = () => useContext(AuthDataContext);
修改PrivateRoute.js,加载状态下不做跳转判定:
const PrivateRoute = ({ component: Component, ...rest }) => { const { isAuth, authLoading } = useAuthDataContext(); console.log("isAuth", isAuth); return <Route {...rest} component={(props) => { if (authLoading) return <div>认证状态加载中...</div>; return isAuth ? <Component {...props} /> : <Redirect to="/" />; }} />; };
2. 登录成功后缺少路由跳转逻辑
你当前登录完成后仍然停留在登录页,需要补充登录后的跳转逻辑。修改LoginPage.js:
首先引入路由跳转hook:
import { useHistory } from 'react-router-dom';
在LoginPage组件内获取history实例:
const LoginPage = () => { const history = useHistory(); // 原有代码不变
修改两处登录成功后的回调,添加跳转:
第一处useEffect内的登录逻辑:
firebase .auth() .signInWithEmailLink(savedEmail, window.location.href) .then(() => { window.localStorage.removeItem("emailForSignIn"); }) .then(onLogin) .then(() => history.push('/dashboard')) // 新增跳转 .catch((error) => { console.log(error); setMessage(error); });
第二处onSubmit内的登录逻辑:
firebase .auth() .signInWithEmailLink(email, window.location.href) .then(() => { window.localStorage.removeItem("emailForSignIn"); }) .then(onLogin) .then(() => history.push('/dashboard')) // 新增跳转 .catch((error) => { console.log(error); });
额外检查项
确认Firebase控制台中,已将localhost加入授权域名列表,且邮箱链接认证功能开关已开启。
内容的提问来源于stack exchange,提问作者Espresso
相关产品推荐
相关产品推荐

