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

React集成Firebase Auth后刷新首页先跳转登录页再返回的问题

问题:Firebase Auth登录状态下刷新首页出现跳转闪烁

我在React应用中基于Firebase Auth实现了认证功能,设置了登录页和仅登录用户可访问的首页。但目前遇到问题:处于登录状态时刷新首页,页面会先跳转到登录页,随后又返回首页,无法排查原因。

相关代码

index.js(省略导入等内容)

root.render(
  <AuthProvider>
    <Router>
      <Toaster />
      <AppRouter />
    </Router>    
  </AuthProvider>    
);

AuthProvider.js

import React, { useEffect, useState } from "react";
import { onAuthStateChanged } from "firebase/auth";
import { FirebaseAuth } from "./firebase/config";

export const AuthContext = React.createContext();

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null);

  useEffect(() => {
    onAuthStateChanged(FirebaseAuth, user => {
      if (user) {
        setCurrentUser(user)
      } else {
        setCurrentUser(null)
      }
    })
  }, []);

  return (
    <AuthContext.Provider value={{ currentUser }}>
      {children}
    </AuthContext.Provider>
  );
};

AppRouter.js

import { useContext } from "react";
import Landing from "./screens/Landing"
import {
  Navigate,
  BrowserRouter,
  Routes,
  Route
} from "react-router-dom";
import Login from "./screens/auth/Login";
import { AuthContext } from './AuthProvider';

const AppRouter = () => {
  const { currentUser } = useContext(AuthContext);

  return (
    <Routes>
      <Route
        path="/"
        element={!!currentUser ? <Landing /> : <Navigate to="/login" />}
        exact
      />
      <Route
        path="/login"
        element={!currentUser ? <Login /> : <Navigate to="/" />}
        exact
      />
    </Routes>
  )
}

export default AppRouter;

问题原因

currentUser初始值为null,而Firebase的onAuthStateChanged是异步执行的。页面刷新后,AuthProvider会先以currentUser = null的状态渲染AppRouter,此时路由判断用户未登录,触发跳转到登录页;等onAuthStateChanged完成认证状态校验,拿到已登录用户信息后,currentUser更新,路由又判断用户已登录,跳回首页,最终导致页面出现跳转闪烁的现象。

解决方法

在AuthProvider中添加加载状态,标记Firebase认证状态是否初始化完成,加载期间不执行路由跳转判断:

1. 修改AuthProvider.js,添加加载状态

import React, { useEffect, useState } from "react";
import { onAuthStateChanged } from "firebase/auth";
import { FirebaseAuth } from "./firebase/config";

export const AuthContext = React.createContext();

export const AuthProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null);
  // 初始化加载状态为true,表示认证状态未完成校验
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 订阅认证状态变化,并保存取消订阅函数
    const unsubscribe = onAuthStateChanged(FirebaseAuth, user => {
      setCurrentUser(user);
      // 认证状态获取完成,标记加载结束
      setLoading(false);
    });
    // 组件卸载时取消订阅,避免内存泄漏
    return unsubscribe;
  }, []);

  return (
    <AuthContext.Provider value={{ currentUser, loading }}>
      {children}
    </AuthContext.Provider>
  );
};

2. 修改AppRouter.js,处理加载状态

import { useContext } from "react";
import Landing from "./screens/Landing"
import {
  Navigate,
  Routes,
  Route
} from "react-router-dom";
import Login from "./screens/auth/Login";
import { AuthContext } from './AuthProvider';

const AppRouter = () => {
  const { currentUser, loading } = useContext(AuthContext);

  // 加载期间显示加载提示,不执行路由跳转逻辑
  if (loading) {
    return <div>加载中...</div>; // 可替换为自定义加载组件
  }

  return (
    <Routes>
      <Route
        path="/"
        element={!!currentUser ? <Landing /> : <Navigate to="/login" />}
        exact
      />
      <Route
        path="/login"
        element={!currentUser ? <Login /> : <Navigate to="/" />}
        exact
      />
    </Routes>
  )
}

export default AppRouter;

内容的提问来源于stack exchange,提问作者crodev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:55:37