React应用登录成功后路由跳转失效问题求助(react-router@6)
问题概述
React应用使用useContext+useReducer处理登录状态,登录功能可正常完成,但登录成功后无法通过react-router@6的useNavigate跳转到/dashboard页面。
相关代码
AuthService代码
const AuthService = async (dispatch) => { const MSAL_CONFIG = {} // 已填充Microsoft Graph API的AD认证配置 const msalInstance = new msal.PublicClientApplication(MSAL_CONFIG); try { const loginResponse = await msalInstance.loginPopup(scopes); var username = loginResponse.account.username; var userid = username.slice(0, username.indexOf("@")); const loginData = { auth_token: loginResponse.idToken, user: { name: loginResponse.account.name, id: userid, email: username, }, }; const sessionData = { user_id: userid, id_token: loginResponse.idToken, access_token: loginResponse.accessToken, } sessionStorage.setItem("currentUser", JSON.stringify(loginData)); dispatch({ type: "LOGIN_SUCCESS", payload: loginData }); return { loginData: loginData, error: null }; } catch (err) { console.log("+++ Login error : ", err); dispatch({ type: "LOGIN_ERROR", error: err }); return { loginData: null, error: err }; } };
Header组件的登录处理代码
const handleLogin = async () => { await AuthService(dispatch) console.log("userDetails.token : " + userDetails.token) if (Boolean(userDetails.token)) { navigate("/dashboard"); } };
问题原因
- 字段名不匹配:AuthService返回的
loginData中,token字段是auth_token,但handleLogin里判断的是userDetails.token,字段名错误导致判断始终为false。 - 状态更新异步性:useReducer的dispatch是异步执行的,调用AuthService后立即读取userDetails,此时状态还未完成更新,即使字段名正确,也可能拿不到最新值。
解决方案
方案一:利用AuthService返回值直接跳转
既然AuthService已经返回登录成功的loginData,直接用这个返回值判断即可,无需等待context状态更新:
const handleLogin = async () => { const { loginData } = await AuthService(dispatch); if (loginData?.auth_token) { navigate("/dashboard"); } };
方案二:修正字段名+监听状态变化跳转
如果必须依赖context中的userDetails状态,可按以下步骤处理:
- 修正判断字段名,改为
userDetails.auth_token - 用useEffect监听状态变化,触发跳转:
import { useEffect } from 'react'; const Header = () => { const { userDetails, dispatch } = useAuthContext(); const navigate = useNavigate(); useEffect(() => { if (userDetails?.auth_token) { navigate("/dashboard"); } }, [userDetails, navigate]); const handleLogin = async () => { await AuthService(dispatch); }; // 其他组件代码 };
额外检查
确保reducer的LOGIN_SUCCESS分支正确处理payload,将auth_token存入状态:
const authReducer = (state, action) => { switch(action.type) { case "LOGIN_SUCCESS": return { ...state, userDetails: action.payload, isAuthenticated: true, error: null }; // 其他分支逻辑 } };
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

