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

无需Context API/Redux,如何用Firebase Auth实现React受保护路由?

React + Firebase 实现路由保护(不使用Context/Redux)

问题背景

开发了一个简易React应用,用户可通过邮箱和密码使用Firebase登录。需求是:已登录用户能访问/profile路由,未登录用户无法访问。

当前代码(修改后仍无效)

import { useEffect, useState } from "react";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { Routes, Route, Navigate } from "react-router-dom";

function App() {
    const auth = getAuth();
    const currUser = auth.currentUser;

  const ProtectedRoute = ({ user, children }) => {
    if (!currUser) {
      return <Navigate to="/" replace />;
    }

    return children;
  };

  return (
    <div>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="signin" element={<SignIn />} />
        <Route path="signup" element={<Signup />} />
        <Route
          path="/profile"
          element={
            <ProtectedRoute user={currUser}>
              <Profile />
            </ProtectedRoute>
          }
        />
        <Route path="*" element={<p>There's nothing here: 404!</p>} />
      </Routes>
    </div>
  );
}

export default App;

问题原因

直接读取auth.currentUser会初始为null,因为Firebase需要异步验证用户登录状态。当访问/profile时,初始currUser为null,受保护路由会立即重定向到/;之后Firebase完成验证并更新currUser为实际用户,但此时重定向已经完成,无法回到/profile。

解决方案(不使用Context/Redux)

通过useState维护用户状态,结合onAuthStateChanged监听状态变化,同时处理加载状态避免过早重定向:

修改后的完整代码

import { useEffect, useState } from "react";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { Routes, Route, Navigate } from "react-router-dom";

function App() {
  // 初始设为undefined,区分「未加载完成」和「未登录」状态
  const [currUser, setCurrUser] = useState(undefined);
  const auth = getAuth();

  useEffect(() => {
    // 监听Firebase用户状态变化
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      setCurrUser(user);
    });

    // 组件卸载时取消监听,避免内存泄漏
    return unsubscribe;
  }, [auth]);

  // 未加载完成时,显示加载提示(可替换为自定义加载组件)
  if (currUser === undefined) {
    return <div>加载中...</div>;
  }

  const ProtectedRoute = ({ children }) => {
    // 确认未登录时才重定向
    if (!currUser) {
      return <Navigate to="/" replace />;
    }
    return children;
  };

  return (
    <div>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="signin" element={<SignIn />} />
        <Route path="signup" element={<Signup />} />
        <Route
          path="/profile"
          element={
            <ProtectedRoute>
              <Profile />
            </ProtectedRoute>
          }
        />
        <Route path="*" element={<p>There's nothing here: 404!</p>} />
      </Routes>
    </div>
  );
}

export default App;

方案说明

  1. 状态区分:用undefined表示Firebase还在验证用户状态,null表示未登录,用户对象表示已登录
  2. 异步监听:onAuthStateChanged会在Firebase完成用户验证后触发,自动更新currUser状态
  3. 加载处理:未加载完成时不渲染路由,避免初始null导致的错误重定向
  4. 路由保护逻辑:只有确认用户未登录(currUser为null)时,才重定向到首页;已登录则正常渲染目标页面

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 04:06:24