React项目中SignInWithRedirect功能异常问题求助
问题描述
- 使用
signInWithRedirect进行谷歌登录时,页面会跳转到谷歌,但仅显示顶部蓝色进度条就立刻返回网站,无法看到谷歌的账号登录/选择界面 - 之前尝试
signInWithPopup时出现跨域错误 - 成功登录一次后,无法再次触发登录流程或切换其他账号;登出后使用同一邮箱登录也失效
相关代码
React主组件代码
import './app.css' import { Route, Routes } from 'react-router-dom' import { Link, useMatch, useResolvedPath } from "react-router-dom" import Home from './pages/home.jsx' import PPapers from './pages/pastp.jsx' import Logo from './images/re.svg' import 'bootstrap/dist/css/bootstrap.min.css'; import { auth, googleProvider } from './config/firebase-config'; import { createUserWithEmailAndPassword, signInWithRedirect, signOut, signInWithEmailAndPassword, getRedirectResult } from 'firebase/auth'; import { useEffect, useState } from 'react'; import Button from 'react-bootstrap/Button'; import Modal from 'react-bootstrap/Modal'; import GoogleLogo from './images/google.png' import { onAuthStateChanged } from 'firebase/auth'; function NavBar(){ const [cLogged, setLoggedIn] = useState(false); const [modalShow, setModalShow] = useState(false); // 优化认证状态监听:只订阅一次 useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (user) => { setLoggedIn(!!user); if (user) { console.log(user.email); } }); // 组件卸载时取消订阅 return unsubscribe; }, []); const logout = async () => { try { await signOut(auth); } catch (err) { console.error(err); } }; return ( <> <div className = "navBar"> <div id='LHS'> <img src= {Logo} alt="" /> <label className="hamburger-menu"> <input type="checkbox" /> </label> <aside className="sidebar"> <nav> <div><CustomLink className = "links" to="/">Home</CustomLink></div> <div><CustomLink className = "links" to="/pastp">Past Papers</CustomLink></div> </nav> </aside> </div> <div id="RHS"> {cLogged ? <button className='accountBtn' onClick={logout}>Logout</button>: <Button variant="primary" className = 'accountBtn'onClick={() => setModalShow(true)}>Log-In</Button>} <SignInPopup show={modalShow} onHide={() => setModalShow(false)} /> <Link id='pBtn'> Get Premium </Link> </div> </div> </> ) } function SignInPopup(props) { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [isLogin, setLogin] = useState(true); const [invalid, setInvalid] = useState(false); // 处理谷歌跳转后的认证结果 useEffect(() => { const handleRedirectResult = async () => { try { const result = await getRedirectResult(auth); if (result) { // 认证成功,关闭弹窗 props.onHide(); } } catch (err) { console.error(err); setInvalid(true); } }; handleRedirectResult(); }, [props]); const signIn = async () => { try { if (isLogin) { // 登录用signInWithEmailAndPassword await signInWithEmailAndPassword(auth, email, password); } else { // 注册用createUserWithEmailAndPassword await createUserWithEmailAndPassword(auth, email, password); } props.onHide(); } catch (err) { console.error(err); setInvalid(true); } }; const signInWithGoogle = async () => { try { // 设置prompt强制显示账号选择界面 googleProvider.setCustomParameters({ prompt: 'select_account' }); await signInWithRedirect(auth, googleProvider); } catch (err) { console.error(err); setInvalid(true); } }; function isInvalid() { return ( email === "" || password === "" || password.length < 6 || !email.includes('@') || !email.includes('.') ); } return ( <Modal {...props} size="md" aria-labelledby="contained-modal-title-vcenter" centered data-bs-theme="dark" className='modal' > <Modal.Header closeButton> <Modal.Title id="contained-modal-title-vcenter"> <h2>RevisionEase</h2> </Modal.Title> </Modal.Header> <Modal.Body> <h4>{isLogin ? 'Sign-in' : 'Sign-Up'}</h4> <p className='signIn' onClick={() => setLogin(!isLogin)}> {isLogin ? 'Sign-Up?' : 'Sign-in?'} </p> <div className='su'> <input placeholder="Enter Email" onChange={e => setEmail(e.target.value)} /> <input placeholder="Enter Password" type='password' onChange={e => setPassword(e.target.value)} /> <button className='signIn' onClick={signIn}>{isLogin ? 'Sign-in' : 'Sign-up'}</button> <p>Or sign-in with:</p> <button className="googlesu" onClick={signInWithGoogle}> <img src={GoogleLogo} alt="" /> </button> <p>{(invalid && isInvalid()) ? 'Please enter your details correctly' : ''}</p> </div> </Modal.Body> <Modal.Footer> <label>Log-in and Sign-up to gain access to more past papers and more!</label> </Modal.Footer> </Modal> ); } function App() { return ( <> <NavBar /> <div className="maincontainer"> <Routes> <Route path="/" element={<Home />} /> <Route path="/pastp" element={<PPapers />} /> </Routes> </div> </> ) } function CustomLink({ to, children, ...props }) { const resolvedPath = useResolvedPath(to) const isActive = useMatch({ path: resolvedPath.pathname, end: true }) return ( <li className={isActive ? "active" : ""}> <Link to={to} {...props}> {children} </Link> </li> ) } export default App;
Firebase配置代码
import { getAuth, GoogleAuthProvider } from "firebase/auth"; import { initializeApp } from "firebase/app"; import { getFirestore } from "firebase/firestore"; import { getStorage } from 'firebase/storage'; const firebaseConfig = { apiKey: "---", authDomain: "---", projectId: "---", storageBucket: "---", messagingSenderId: "---", appId: "---", measurementId: "---" }; const app = initializeApp(firebaseConfig); export const auth = getAuth(app); export const googleProvider = new GoogleAuthProvider(); export const db = getFirestore(app); export const storage = getStorage(app);
关键修复点
- 处理
signInWithRedirect的回调:在SignInPopup组件中添加getRedirectResult调用,负责接收谷歌跳转后的认证结果,否则Firebase无法完成认证流程,会直接返回网站。 - 强制账号选择:在
signInWithGoogle中设置googleProvider.setCustomParameters({ prompt: 'select_account' }),避免谷歌自动登录已保存的账号,解决无法切换账号的问题。 - 修复登录/注册逻辑:原代码中不管登录还是注册都用
createUserWithEmailAndPassword,登录应该调用signInWithEmailAndPassword。 - 优化认证状态监听:
NavBar中的onAuthStateChanged只订阅一次,避免重复监听导致的状态异常,同时组件卸载时取消订阅。 - 跨域问题(Popup模式):登录Firebase控制台,进入认证->设置->授权域名,添加你的本地开发域名(比如
localhost:3000),解决signInWithPopup的跨域错误。
内容的提问来源于stack exchange,提问作者Mohammed Aayan Pathan
相关产品推荐
相关产品推荐

