You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 16:57:33