React Firebase登录跳转异常:需刷新进首页的修复咨询
问题描述
在React项目中集成Firebase身份验证,调用signInWithEmailAndPassword完成登录后执行navigate('/'),却被重定向到/landing页面,必须刷新才能进入首页。相关代码如下:
登录组件(Login Component)
import React, { useState } from "react"; import { Link, useNavigate } from "react-router-dom"; import { signInWithEmailAndPassword } from "firebase/auth"; import { auth } from "./firebase.js"; export default LoginComponent = () => { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const navigate = useNavigate(); const handleSubmit = (e) => { e.preventDefault(); signInWithEmailAndPassword(auth, email, password).then(() => { navigate('/') }).catch((error) => { }); }; // 组件渲染代码省略 };
身份验证提供者(AuthProvider)
import { onAuthStateChanged } from "firebase/auth"; import { createContext, useEffect, useState } from "react"; import PropTypes from "prop-types"; import { auth } from "./firebase.js"; export const AuthContext = createContext(null); const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [accessToken, setAccessToken] = useState(null); useEffect(() => { const unsubscribe = onAuthStateChanged(auth, async (currentUser) => { if (currentUser) { setAccessToken(await currentUser.getIdToken(true)); } setUser(currentUser); setLoading(false); }); return () => unsubscribe(); }, []); const authValue = { user, loading, accessToken, }; return <AuthContext.Provider value={authValue}>{children}</AuthContext.Provider>; }; AuthProvider.propTypes = { children: PropTypes.node.isRequired, }; export default AuthProvider;
路由页面代码
import { useContext } from 'react' import { AuthContext } from "./components/Auth/AuthProvider.js"; import UserProfile from "./components/UserProfile" import { Navigate } from 'react-router-dom'; const App = () => { const { user, loading } = useContext(AuthContext); function LandingPageRedirect({ children }) { if (loading) { return <div>Loading...</div>; } if (user) { return <>{children}</> } else { return ( <Navigate to="/landing" state={{ from: location.pathname, }} replace /> ) } } return ( <div> <BrowserRouter> <Routes> <Route path='/' element={ <LandingPageRedirect> <Home /> </LandingPageRedirect> } /> {/* 其他路由省略 */} </Routes> </BrowserRouter> </div> ); };
解决方案
1. 修复登录组件:监听用户状态变化再跳转
登录成功后直接调用navigate时,AuthContext的user状态尚未更新,路由守卫会读取旧的null值导致重定向。改为监听user状态,确认用户已登录后再跳转:
import React, { useState, useContext, useEffect } from "react"; import { Link, useNavigate } from "react-router-dom"; import { signInWithEmailAndPassword } from "firebase/auth"; import { auth } from "./firebase.js"; import { AuthContext } from "./AuthProvider"; // 根据实际路径调整 // 修复导出语法 export default function LoginComponent() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const navigate = useNavigate(); const { user } = useContext(AuthContext); // 监听user状态,存在时跳转首页 useEffect(() => { if (user) { navigate('/'); } }, [user, navigate]); const handleSubmit = (e) => { e.preventDefault(); signInWithEmailAndPassword(auth, email, password) .catch((error) => { // 添加错误处理,比如提示用户 console.error('登录失败:', error.message); }); }; // 组件渲染代码... }
2. 调整AuthProvider状态更新顺序(可选)
将setUser提前到getIdToken之前,确保用户状态优先更新,路由守卫能更快检测到已登录状态:
useEffect(() => { const unsubscribe = onAuthStateChanged(auth, async (currentUser) => { // 先更新user状态 setUser(currentUser); if (currentUser) { setAccessToken(await currentUser.getIdToken(true)); } else { setAccessToken(null); // 登出时清除token } setLoading(false); }); return () => unsubscribe(); }, []);
3. 修复路由守卫中的location未定义问题
LandingPageRedirect组件中location变量未声明,需导入并使用useLocation钩子:
import { Navigate, useLocation } from 'react-router-dom'; import { useContext } from 'react'; import { AuthContext } from "./components/Auth/AuthProvider.js"; function LandingPageRedirect({ children }) { const location = useLocation(); // 添加这行 const { user, loading } = useContext(AuthContext); if (loading) { return <div>Loading...</div>; } if (user) { return <>{children}</>; } else { return ( <Navigate to="/landing" state={{ from: location.pathname, }} replace /> ); } }
内容的提问来源于stack exchange,提问作者JobHunter69
相关产品推荐
相关产品推荐

