React+Firebase第三方登录后无法自动跳转至用户仪表盘问题
解决React + Firebase第三方登录后无法自动跳转受保护路由的问题
问题描述
使用React和Firebase实现受保护路由时,邮箱登录可正常跳转至Dashboard,但Google、Facebook等第三方登录后,页面会在用户认证状态更新前重定向回登录页;手动刷新页面后,可正常进入受保护的Dashboard页面。
原因分析
- 登录状态同步延迟:第三方登录(弹窗模式)的异步流程耗时稍长,Redux中
currentUser状态更新慢于路由跳转时机,导致ProtectedRoute检测不到已登录用户,重定向回登录页。 - 本地loading状态冗余:Login组件使用本地
loading状态而非Redux全局状态,且useEffect未监听该状态,无法在登录过程中正确触发跳转逻辑。 - ProtectedRoute无加载状态处理:登录过程中
loading为true时,ProtectedRoute直接重定向,未等待currentUser状态更新完成。
解决方案
1. 优化ProtectedRoute,添加加载状态处理
修改protectedRoute.js,在登录加载过程中显示加载组件,而非直接重定向:
import React from 'react'; import { useSelector } from 'react-redux'; import LoadingToRedirect from './LoadingToRedirect'; const ProtectedRoute = ({children}) => { const { currentUser, loading } = useSelector((state) => state.user); // 登录过程中显示加载,避免提前重定向 if (loading) { return <div>加载中...</div>; // 可替换为自定义加载组件 } return currentUser ? children : <LoadingToRedirect />; } export default ProtectedRoute;
2. 重构Login组件,移除本地loading状态
删除Login组件中的本地loading状态,直接使用Redux全局状态,并优化useEffect的触发条件:
import React, { useState, useEffect } from 'react'; import { useDispatch, useSelector} from "react-redux"; import { useNavigate, Link } from "react-router-dom"; import { fbSignInInitiate, googleSignInInitiate, loginInitiate } from '../../userauth/actions'; import './login.css'; const Login = () => { const [state, setState] = useState({ email: "", password: "", }); const { email, password } = state; // 从Redux获取全局状态 const { currentUser, loading } = useSelector((state) => state.user); const navigate = useNavigate(); const dispatch = useDispatch(); // 仅当currentUser存在时跳转,依赖currentUser和navigate useEffect(() => { if (currentUser) { navigate("/dashboard"); } }, [currentUser, navigate]); const handleGoogleSignIn = () => { dispatch(googleSignInInitiate()); }; const handleFBSignIn = () => { dispatch(fbSignInInitiate()); }; const handleSubmit = (e) => { e.preventDefault(); if(!email || !password) { return; } dispatch(loginInitiate(email, password)); setState({ email: "", password: "" }); }; const handleChange = (e) => { let { name, value } = e.target; setState({...state, [name]: value }); }; return ( <div> <div id="logreg-form"> <form className='form-signin' onSubmit={handleSubmit}> <h1>Sign in</h1> <div className="social-login"> <button className='btn google-btn social-btn' type='button' onClick={handleGoogleSignIn}> <span> <i className='fab fa-google-plus-g'>Sign in with Google</i> </span> </button> <button className='btn facebook-btn social-btn' type='button' onClick={handleFBSignIn}> <span> <i className='fab fa-facebook-f'>Sign in with Facebook</i> </span> </button> </div> <p>OR</p> <input type="email" id="inputEmail" className='form-control' placeholder='Email Address' name="email" onChange={handleChange} value={email} required /> <input type="password" id="inputPassword" className='form-control' placeholder='Password' name="password" onChange={handleChange} value={password} required /> <button className='btn btn-secondary btn-block' type="submit"> <i className="fas fa-sign-in-alt"></i>Sign In </button> <hr /> <p>Don't have an account</p> <Link to="/signup"> <button className='btn btn-primary btn-block' type="button" id="btn-signup"> <i className='fas fa-user-plus'></i>Sign up New Account </button> </Link> </form> </div> </div> ) } export default Login;
3. 修复userReducer的logout状态处理
在reducer.js的LOGOUT_SUCCESS case中添加loading: false,避免logout后loading状态残留:
case types.LOGOUT_SUCCESS: return { ...state, currentUser: null, loading: false, // 新增:重置loading状态 }
4. 优化注册流程的异步逻辑
修改Actions.js中的registerInitiate,确保updateProfile完成后再dispatch成功状态:
export const registerInitiate = (email, password, displayName) => { return async function (dispatch) { dispatch(registerStart()); try { const { user } = await auth.createUserWithEmailAndPassword(email, password); await user.updateProfile({ displayName }); // 等待昵称更新完成 dispatch(registerSuccess(user)); } catch (error) { dispatch(registerFail(error.message)); } } };
修改后效果
第三方登录完成后,Redux状态更新时,Login组件会自动触发跳转至Dashboard;ProtectedRoute在登录加载过程中显示加载状态,避免提前重定向,确保用户状态同步完成后再进入受保护页面。
内容的提问来源于stack exchange,提问作者happypenguin
相关产品推荐
相关产品推荐

