React中loggedIn状态自动回退为false的问题排查与修复
问题:Google登录后Redux状态
loggedIn自动变回false,页面跳转后回到登录页 我添加了Google按钮用于谷歌账号登录,Redux中有一个名为loggedIn的状态属性,初始值为false。点击Google按钮登录时,会dispatch login reducer,状态更新为true并导航到home页面,但状态随即又更新为false,页面回到登录页。
问题原因
signInWithRedirect的异步重定向特性:signInWithRedirect是异步操作,会触发页面重定向刷新。当前代码中在调用它后立刻dispatchlogin并导航,页面刷新后Redux状态会重置为初始值(Redux默认不持久化状态),导致loggedIn变回false。- 未同步Firebase与Redux状态:页面刷新后,没有检查Firebase的实际用户登录状态,Redux状态无法与Firebase用户状态同步。
- Navbar登出逻辑错误:登出按钮直接调用
auth.signOut()但未关联Redux的logoutdispatch,不过这不是当前问题的直接诱因。
修复方案
1. 处理Google登录重定向结果
修改Authentication.jsx,在组件挂载时处理重定向后的登录结果,确保登录成功后再更新状态:
import React, { useState, useEffect } from 'react'; import SignIn from '../components/SignIn'; import SignUp from '../components/SignUp'; import { auth } from '../firebase/firebase'; import { signInWithRedirect, GoogleAuthProvider, getRedirectResult } from 'firebase/auth'; import GoogleButton from 'react-google-button'; import { useNavigate } from 'react-router-dom'; import { login } from '../redux/slice'; import { useDispatch } from 'react-redux'; const Authentication = () => { const [page, setPage] = useState(true); const [data, setData] = useState({ email: '', password: '' }); const [signUpData, setSignUpdData] = useState({ firstName: '', lastName: '', email: '', password: '', confirmPassword: '', phoneNumber: '', dateOfBirth: '', }); const pageHandler = () => { setPage(!page); }; const dataHandler = event => { event.preventDefault(); setData({ ...data, [event.target.name]: event.target.value }); }; const signUpDataHandler = event => { event.preventDefault(); setSignUpdData({ ...signUpData, [event.target.name]: event.target.value }); }; const navigate = useNavigate(); const dispatch = useDispatch(); // 处理Google登录重定向结果 useEffect(() => { const handleRedirectResult = async () => { try { const result = await getRedirectResult(auth); if (result?.user) { dispatch(login()); navigate('/', { replace: true }); } } catch (error) { console.error('登录失败:', error); } }; handleRedirectResult(); }, [dispatch, navigate]); // Google Button sign in const signInWithGoogle = () => { const provider = new GoogleAuthProvider(); signInWithRedirect(auth, provider); }; return ( <div className="container mt-5"> <div className="card mx-auto w-75 bg-success p-4"> <div className="card-body "> {page ? ( <SignIn data={data} dataHandler={dataHandler} /> ) : ( <SignUp signUpData={signUpData} signUpDataHandler={signUpDataHandler} /> )} </div> </div> <div className="d-flex w-75 mx-auto my-3 align-items-center"> <hr className="w-100 m-0 p-0" /> <p className="m-0 mx-3">or</p> <hr className="w-100 m-0 p-0" /> </div> <div className="d-flex justify-content-center"> <div> <GoogleButton onClick={signInWithGoogle} /> </div> </div> <button className="btn btn-outline-success mx-auto d-block my-3" onClick={pageHandler}> {page ? 'Sign Up' : 'Sign In'} </button> </div> ); }; export default Authentication;
2. 同步Firebase与Redux状态
修改App.jsx,监听Firebase用户状态,确保页面刷新后Redux状态与实际登录状态同步:
import React, { useEffect } from 'react'; import 'bootstrap/dist/css/bootstrap.css'; import 'bootstrap/dist/js/bootstrap.min.js'; import 'bootstrap-icons/font/bootstrap-icons.css'; import Home from './pages/Home'; import Authentication from './pages/Authentication'; import { Routes, Route, Navigate } from 'react-router-dom'; import { useSelector, useDispatch } from 'react-redux'; import { auth } from './firebase/firebase'; import { useAuthState } from 'react-firebase-hooks/auth'; import { login, logout } from './redux/slice'; const App = () => { const { loggedIn } = useSelector(state => state.item); const dispatch = useDispatch(); const [user] = useAuthState(auth); // 根据Firebase用户状态同步Redux useEffect(() => { if (user) { dispatch(login()); } else { dispatch(logout()); } }, [user, dispatch]); console.log("App", loggedIn); let routes; if (loggedIn) { routes = ( <Routes> <Route path="/" element={<Home />} /> <Route path="/home" element={<Home />} /> <Route path="/logout" element={<Authentication />} /> <Route path="*" element={<Navigate to="/" replace />} /> </Routes> ); } else { routes = ( <Routes> <Route path="/auth" element={<Authentication />} /> <Route path="*" element={<Navigate to="/auth" replace />} /> </Routes> ); } return <> {routes} </>; }; export default App;
3. 修复Navbar登出逻辑
修改Navbar.jsx,确保登出时同步更新Firebase和Redux状态:
import React from 'react'; import './navbar.scss'; import { Link } from 'react-router-dom'; import { useDispatch } from 'react-redux'; import { logout } from '../redux/slice'; import { auth } from '../firebase/firebase'; const Navbar = ({ user }) => { console.log('nav', user); const dispatch = useDispatch(); const signOut = () => { auth.signOut(); dispatch(logout()); }; return ( <div className="bg-success navigation"> <div className="chats d-flex flex-column align-items-center"> <Link to="/"> <i className="bi bi-house text-light" style={{ fontSize: '30px' }} /> </Link> <Link to="/logout"> <i className="bi bi-sign-turn-left text-light" onClick={signOut} style={{ fontSize: '30px' }} /> </Link> </div> <div className="profile"> <Link to="/" className="profile-link"> <img className="profile-picture" src="https://res.cloudinary.com/djz3p8sux/image/upload/v1660556173/image/IMG_20220703_174147_w8fbhq.jpg" alt="profile-picture" /> </Link> </div> </div> ); }; export default Navbar;
内容的提问来源于stack exchange,提问作者Mahbubul Hasan
相关产品推荐
相关产品推荐

