Firebase登出按钮无法跳转至登录页面的问题排查与解决
问题:Firebase登出后无法跳转到Login页面
我正在学习Firebase,设置了基于user.emailVerified的路由规则。点击页面上的Log Out按钮后,无法跳转到Login页面,虽然登出后用户状态变为null,但跳转仍失效。以下是相关代码:
Nav.jsx
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
相关产品推荐
相关产品推荐

