React项目刷新Dashboard时短暂显示登录页是否正常及解决方法
登录后刷新Dashboard页面短暂显示登录页的原因及解决方案
问题描述
React项目包含登录、注册、Dashboard路由,通过Google登录完成鉴权,登录后可进入Dashboard页面。但刷新Dashboard时,会短暂显示登录页面(约1秒),需解决该异常问题。
原因分析
这种情况不正常,核心诱因如下:
- 鉴权状态初始化时
user为null,导致signed初始值为false,PrivateRoutes会优先触发跳转到登录页 - 从
sessionStorage加载用户信息的逻辑在useEffect中执行,属于组件挂载后的异步操作,此时组件已完成首次渲染,因此会先显示登录页,等setUser更新状态后才会跳转回Dashboard - 额外问题:
useEffect未设置依赖数组,会在组件每次渲染时重复执行;从sessionStorage取出用户信息时未做JSON.parse解析,直接将字符串赋值给user
解决方案
1. 添加加载状态,避免初始错误跳转
在Auth上下文新增loading状态,用于标识用户信息是否加载完成。加载完成前,PrivateRoutes不做跳转,而是显示加载提示(如Spinner)。
2. 修正useEffect依赖与数据解析
- 给
useEffect添加空依赖数组,确保仅在组件挂载时执行一次 - 取出
sessionStorage中的用户信息时,用JSON.parse将字符串解析为对象
修改后的代码
调整后的Google上下文代码
import { useState, useEffect, createContext } from "react"; import { getAuth, GoogleAuthProvider, signInWithPopup } from "firebase/auth"; export const AuthGoogleContext = createContext({}); export const AuthGoogleProvider = ({ children }) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); // 新增加载状态 const auth = getAuth(app); const provider = new GoogleAuthProvider(); useEffect(() => { const loadStorageData = () => { const storageUser = sessionStorage.getItem("@Auth:user"); const storageToken = sessionStorage.getItem("@Auth:token"); if (storageToken && storageUser) { setUser(JSON.parse(storageUser)); // 解析JSON字符串为对象 } setLoading(false); // 加载完成后设置loading为false }; loadStorageData(); }, []); // 添加空依赖数组,仅执行一次 const signGoogle = () => { signInWithPopup(auth, provider) .then((result) => { const credential = GoogleAuthProvider.credentialFromResult(result); const token = credential.accessToken; const user = result.user; setUser(user); sessionStorage.setItem("@Auth:token", token); sessionStorage.setItem("@Auth:user", JSON.stringify(user)); }) .catch((error) => { console.log(error.code); }); }; function signOut() { sessionStorage.clear(); setUser(null); } return ( <AuthGoogleContext.Provider value={{ signGoogle, signed: !!user, user, signOut, loading }} > {children} </AuthGoogleContext.Provider> ); };
调整后的PrivateRoutes代码
import { useContext } from "react"; import { Navigate, Outlet } from "react-router-dom"; import { AuthGoogleContext } from "../context/authGoogle"; export const PrivateRoutes = () => { const { signed, loading } = useContext(AuthGoogleContext); // 加载中时显示加载组件(可替换为自定义Spinner) if (loading) { return <div>加载中...</div>; } return signed ? <Outlet /> : <Navigate to="/login" />; };
额外优化建议
- 可将加载组件替换为更友好的全局Spinner,提升用户体验
- 建议对存储的token做有效性校验(比如调用Google官方验证接口),避免过期token导致的鉴权异常
内容的提问来源于stack exchange,提问作者carlos sodre
相关产品推荐
相关产品推荐

