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

Firebase登出按钮无法跳转至登录页面的问题排查与解决

问题:Firebase登出后无法跳转到Login页面

我正在学习Firebase,设置了基于user.emailVerified的路由规则。点击页面上的Log Out按钮后,无法跳转到Login页面,虽然登出后用户状态变为null,但跳转仍失效。以下是相关代码:

import { getAuth, signOut } from 'firebase/auth';
import React from 'react';
import { useDispatch } from 'react-redux';
import { Link, useNavigate } from 'react-router-dom';
import { setLogOut } from '../redux/slice';

const Nav = () => {
  const navigate = useNavigate();
  const auth = getAuth();
  const dispatch = useDispatch()


  const logOutHandler = () => {
    signOut(auth)
      .then(() => {
        dispatch(setLogOut())
        navigate('/login', { replace: true });
      })
      .catch(error => {
        console.log(error);
      });
  };

  return (
    <nav className="navbar navbar-expand-lg bg-light ">
      <div className="container">
        <Link className="navbar-brand" to="/">
          Navbar
        </Link>
        <Link className="nav-link" to="/">
          Home
        </Link>
        <button className="btn btn-outline-secondary" onClick={logOutHandler}>
          Log Out
        </button>
      </div>
    </nav>
  );
};

export default Nav;

App.jsx

import React, { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import 'bootstrap-icons/font/bootstrap-icons.css';
import { Routes, Route, Navigate } from 'react-router-dom';
import Nav from './components/Nav';
import Home from './pages/Home';
import Login from './pages/Login';
import SignUp from './pages/SignUp';
import EmailVerify from './pages/EmailVerify';
import { getAuth, onAuthStateChanged } from 'firebase/auth';

const App = () => {
  const [verified, setverified] = useState();

  // get user information
  const auth = getAuth();
  onAuthStateChanged(auth, user => {
    if (user) {
      setverified(user.emailVerified);
    } else {
      // User is signed out
      // ...
    }
  });

  let routes;
  if (verified) {
    routes = (
      <>
        <Nav />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="*" element={<Navigate to="/" replace />} />
        </Routes>
      </>
    );
  } else {
    routes = (
      <>
        <Routes>
          <Route path="/login" element={<Login />} />
          <Route path="/signup" element={<SignUp />} />
          <Route path="/email-verify" element={<EmailVerify />} />
          <Route path="*" element={<Navigate to="/login" replace />} />
        </Routes>
      </>
    );
  }

  return <>{routes}</>;
};

export default App;

redux切片

import { createSlice } from '@reduxjs/toolkit';
import { getAuth, onAuthStateChanged } from 'firebase/auth';

const initialState = {
  email: JSON.parse(localStorage.getItem('email')),
  isLoggedIn: JSON.parse(localStorage.getItem('loggedInStatus')),
};

export const slice = createSlice({
  name: 'slice',
  initialState,
  reducers: {
    setLogInValue: (state, action) => {
      localStorage.setItem('email', JSON.stringify(action.payload));
      localStorage.setItem('loggedInStatus', JSON.stringify(true));

      state.email = action.payload;
      state.isLoggedIn = true;
    },
    setLogOut: state => {
      localStorage.setItem('email', null);
      localStorage.setItem('loggedInStatus', false);

      state.email = null;
      state.isLoggedIn = false;
    },
  },
});

export const { setLogInValue, setLogOut } = slice.actions;

export default slice.reducer;

问题原因

App组件的onAuthStateChanged监听逻辑存在遗漏:当用户登出(user为null)时,没有更新verified状态。初始时verified为undefined,登出后依然保留之前的true值,导致路由仍渲染已验证用户的配置(包含Nav和Home路由)。此时执行navigate('/login')后,会被路由规则里的<Route path="*" element={<Navigate to="/" replace />} />强制跳回首页,表现为跳转失效。

解决方案

1. 修复用户登出时的状态更新

修改App.jsx中的onAuthStateChanged逻辑,在用户登出时将verified设为false:

onAuthStateChanged(auth, user => {
  if (user) {
    setverified(user.emailVerified);
  } else {
    // 用户登出时更新verified状态
    setverified(false);
  }
});

2. 优化初始状态取值

避免初始verified为undefined导致路由判断异常,结合当前用户状态设置初始值:

const auth = getAuth();
const [verified, setverified] = useState(() => {
  const currentUser = auth.currentUser;
  return currentUser ? currentUser.emailVerified : false;
});

3. 可选:封装私有路由组件(优化路由结构)

创建PrivateRoute组件统一验证逻辑,让路由结构更清晰:

const PrivateRoute = ({ children }) => {
  const auth = getAuth();
  const user = auth.currentUser;
  if (!user || !user.emailVerified) {
    return <Navigate to="/login" replace />;
  }
  return children;
};

然后在App.jsx中使用:

return (
  <>
    {auth.currentUser && <Nav />}
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route path="/signup" element={<SignUp />} />
      <Route path="/email-verify" element={<EmailVerify />} />
      <Route path="/" element={
        <PrivateRoute>
          <Home />
        </PrivateRoute>
      } />
      <Route path="*" element={<Navigate to="/login" replace />} />
    </Routes>
  </>
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 02:09:10