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

React Router v6配合Firebase v9登录后无法跳转主页且抛状态更新警告

问题解决步骤

错误原因

  1. 自定义Hook useAuth 缺少加载状态标识:onAuthStateChanged 是异步触发的,首次渲染时currentUser初始值为undefined,无法区分「还在加载鉴权状态」和「用户未登录」两种场景,导致RequireAuth组件直接触发跳转到登录页,组件被提前卸载。
  2. 鉴权状态回调执行时,RequireAuth已经被卸载,此时尝试更新组件内部的currentUser状态,就会触发控制台的内存泄漏警告。
  3. 之前尝试的异步私有路由写法不符合React Hook使用规则:Hook只能在组件顶层作用域调用,不能放在async函数内部,也不能用await接收Hook返回值。
  4. 不应该在App组件内部定义RequireAuth组件,每次App重新渲染都会重建RequireAuth,导致不必要的组件重新挂载。

修复方案

1. 修改useAuth自定义Hook,新增加载状态

在firebase.js的useAuth中新增loading状态,标识鉴权状态是否加载完成:

export function useAuth() {
  const [currentUser, setCurrentUser] = useState();
  // 新增加载状态,初始为true
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    const unsub = onAuthStateChanged(auth, user => {
      setCurrentUser(user);
      // 拿到用户状态后设置加载完成
      setLoading(false);
    });
    return unsub;
  }, [])
  // 返回对象包含用户信息和加载状态
  return { currentUser, loading };
}

2. 改造RequireAuth组件,移到App组件外部定义

加载完成前先返回占位内容,避免提前跳转:

// 将RequireAuth提到App组件外部定义
import { Navigate, Outlet } from "react-router-dom";
import { useAuth } from "./firebase";

function RequireAuth() {
  const { currentUser, loading } = useAuth();
  // 鉴权状态未加载完成时返回加载提示
  if (loading) return <div>鉴权中...</div>;
  // 加载完成后判断是否登录,未登录才跳转
  if (!currentUser) { 
    return <Navigate to="/login"/>;
  }
  return <Outlet />
}

function App() {
  const [mainSection, setMainSection] = useState("home");

  const d = new Date();
  const time = d.getHours();
  if (time >= 18 || time < 5) {
    document.documentElement.classList.add("dark");
  }

  return (
      <BrowserRouter>
      <Routes>
        <Route element={<RequireAuth/>}>
          <Route path="/" element={<Home mainSection={mainSection} setMainSection={setMainSection} />}/>
        </Route>
        <Route path="/login" element={<Login />} />
        <Route path="/signup" element={<Signup />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

3. 登录页添加成功跳转逻辑

在Login组件中调用登录接口成功后,用useNavigate跳转到主页即可:

import { useNavigate } from 'react-router-dom';
import { login } from '../firebase';

function Login() {
  const navigate = useNavigate();
  // 表单提交触发的登录逻辑示例
  const handleSubmit = async (e) => {
    e.preventDefault();
    const email = e.target.email.value;
    const password = e.target.password.value;
    try {
      await login(email, password);
      // 登录成功跳主页
      navigate('/');
    } catch (err) {
      // 登录失败提示错误,留在当前页
      alert('登录失败:' + err.message);
    }
  }
  // 剩余组件逻辑省略
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 19:54:06