Firebase登录组件无法跳转至Dashboard组件问题求助
问题描述
我正在使用Firebase Authentication服务,期望用户输入账号密码登录成功后自动跳转至Dashboard组件,但当前Dashboard的路由无法正常生效。查阅Firebase官方文档未找到有效解决办法,恳请各位开发者帮忙解决。
相关代码
SignInForm.js
import React, { useState } from "react"; import { useNavigate } from "react-router-dom/dist"; import { signInWithEmailAndPassword, getAuth } from "firebase/auth"; const SignInForm = () => { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const auth = getAuth(); const signIn = (e) => { e.preventDefault(); signInWithEmailAndPassword(auth, email, password) .then((userCredential) => { console.log(userCredential); }) .catch((error) => { console.log(error); }); }; let navigate = useNavigate(); const routeChange = () => { let path = `/resetpass`; navigate(path); }; return ( <div onClick={signIn}> <div className="sign min-h-screen bg-base-200"> <div className="hero-content flex-col lg:flex-row-reverse"> <div className="text-center lg:text-left"> <h1 className="text-5xl font-bold">Sign In</h1> </div> <div className="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100"> <div className="card-body"> <div className="form-control"> <label className="label"> <span className="label-text">Email</span> </label> <input type="email" placeholder="email" value={email} onChange={(e) => setEmail(e.target.value)} className="input input-bordered" /> </div> <div className="form-control"> <label className="label"> <span className="label-text">Password</span> </label> <input type="password" placeholder="password" value={password} onChange={(e) => setPassword(e.target.value)} className="input input-bordered" /> </div> <label className="label"> <a href="#" onClick={routeChange}> Forgot Password? </a> </label> {/*<div>{active === true && <PasswordReset />}</div> */} <div className="form-control mt-6"> <button type="submit" className="btn btn-primary"> Sign In </button> </div> </div> </div> </div> </div> </div> ); }; export default SignInForm;
Dashboard.js
import { useEffect, useState } from "react"; import { Navigate } from "react-router-dom"; const Dashboard = () => { const [authenticated, setauthenticated] = useState(null); useEffect(() => { const loggedInUser = localStorage.getItem("authenticated"); if (loggedInUser) { setauthenticated(loggedInUser); } }, []); if (!authenticated) { // Redirect return <Navigate replace to="/login" />; } else { return ( <div> <p>Welcome to your Dashboard</p> </div> ); } }; export default Dashboard;
App.js
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import { Fragment } from "react"; import Home from "./Home/pages/Home"; import Navbar from "./shared/components/navigation/Navbar"; import "./App.css"; import React from "@heroicons/react"; import Contact from "./Contact/pages/Contact"; import Admin from "./Admin/pages/Admin"; import SignInForm from "./Contact/components/SignInForm"; import PasswordReset from "./Contact/components/PasswordReset"; import Dashboard from "./Contact/components/Dashboard"; function App() { return ( <div className="root-div"> <Router> <main> <Routes> <Route path="/signin" exact element={<SignInForm />} /> <Route path="/dashboard" exact element={<Dashboard />} /> </Routes> </main> </Router> </div> ); } export default App;
解决方案
1. 修复登录成功后的跳转逻辑(SignInForm.js)
- 移除外层div的
onClick={signIn},改用form标签包裹表单元素,将signIn绑定到form的onSubmit事件,避免误触发登录 - 在登录成功的
then回调中添加跳转代码,并设置登录状态标记 - 修正
useNavigate的导入路径,去掉/dist
修改后的关键代码片段:
import { useNavigate } from "react-router-dom"; // 修正导入路径 const SignInForm = () => { // ...其他代码 const signIn = (e) => { e.preventDefault(); signInWithEmailAndPassword(auth, email, password) .then((userCredential) => { console.log(userCredential); // 登录成功后跳转至Dashboard并标记登录状态 localStorage.setItem('authenticated', 'true'); navigate('/dashboard'); }) .catch((error) => { console.log(error); }); }; // ...其他代码 return ( <div className="sign min-h-screen bg-base-200"> <div className="hero-content flex-col lg:flex-row-reverse"> {/* ...其他代码 */} <div className="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100"> <div className="card-body"> {/* 用form标签包裹表单元素 */} <form onSubmit={signIn}> {/* ...邮箱、密码输入框 */} <div className="form-control mt-6"> <button type="submit" className="btn btn-primary"> Sign In </button> </div> </form> </div> </div> </div> </div> ); };
2. 修复Dashboard的认证校验与路由跳转(Dashboard.js)
- 修正跳转路径为
/signin,与App.js中的登录路由匹配 - 改用Firebase的
onAuthStateChanged监听登录状态,比localStorage更可靠
修改后的完整代码:
import { useEffect, useState } from "react"; import { Navigate } from "react-router-dom"; import { getAuth, onAuthStateChanged } from "firebase/auth"; const Dashboard = () => { const [authenticated, setAuthenticated] = useState(null); const auth = getAuth(); useEffect(() => { // 监听Firebase用户登录状态 const unsubscribe = onAuthStateChanged(auth, (user) => { setAuthenticated(!!user); // 存在用户则标记为已认证 }); return () => unsubscribe(); // 组件卸载时取消监听 }, [auth]); if (authenticated === null) { // 加载状态,可添加自定义loading组件 return <div>Loading...</div>; } if (!authenticated) { return <Navigate replace to="/signin" />; // 修正跳转路径 } else { return ( <div> <p>Welcome to your Dashboard</p> </div> ); } }; export default Dashboard;
3. 确认路由配置(App.js)
当前路由已正确配置/signin和/dashboard,无需额外修改,若后续新增页面可按需添加路由规则。
内容的提问来源于stack exchange,提问作者Lajibolala
相关产品推荐
相关产品推荐

