React+Firebase登录后未跳转/profile 报表单未连接错误
问题描述
我正在使用Reactjs和Firebase开发Netflix克隆项目,已完成Firebase侧登录功能配置,但在应用内执行登录操作时,页面未路由跳转至localhost:3000/profile,始终停留在登录页面。
控制台报错信息:
Form submission canceled because the form is not connected
相关代码文件
App.js
import React, { useEffect } from 'react'; import './App.css'; import HomeScreen from './screens/HomeScreen'; import requests from './Requests'; import {BrowserRouter as Router,Routes,Route}from"react-router-dom"; import LoginScreen from './screens/LoginScreen'; import { auth } from './firebase'; import { useDispatch, useSelector } from 'react-redux'; import { login, logout, selectUser } from './features/userSlice'; import ProfileScreen from './screens/ProfileScreen'; function App() { const user = useSelector(selectUser); const dispatch = useDispatch(); useEffect(() => { const unsubscribe = auth.onAuthStateChanged((userAuth) => { if (userAuth) { dispatch( login({ uid: userAuth.uid, email: userAuth.email, })) } else { dispatch(logout); } }); return unsubscribe; },[dispatch]); return ( <div className="app"> <Router> {!user ? ( <LoginScreen /> ): ( <Routes> <Route path='/profile' element={<ProfileScreen />} /> <Route exact path='/' element={<HomeScreen />} /> </Routes> )} </Router> </div> ); } export default App;
SignupScreen.js
import React, { useRef } from 'react'; import { auth } from '../firebase'; import './SignupScreen.css'; function SignupScreen() { const emailRef = useRef(null); const passwordRef = useRef(null); const register = (e) => { e.preventDefault(); auth.createUserWithEmailAndPassword( emailRef.current.value, passwordRef.current.value ).then((authUser) => { console.log(authUser); }) .catch((error) => { alert(error.message); }); }; const signIn = (e) => { e.preventDefault(); auth.signInWithEmailAndPassword( emailRef.current.value, passwordRef.current.value ).then((authUser) => { console.log(authUser); }) .catch((error) => { alert(error.message); }); }; return ( <div className='signupScreen'> <form> <h1>Sign In</h1> <input ref={emailRef} placeholder='email' type='email' autoComplete='off' /> <input ref={passwordRef} placeholder='password' type='password' autoComplete='off' /> <button type='submit' onClick={signIn}>Sign In</button> <h4> <span className="signupScreen__gray">New to Netflix? </span> <span className="signupScreen__link" onClick={register}> Sign Up now.</span> </h4> </form> </div> ) } export default SignupScreen;
ProfileScreen.js
import React from 'react'; import { useSelector } from 'react-redux'; import { selectUser } from '../features/userSlice'; import { auth } from '../firebase'; import Nav from '../Nav'; import './ProfileScreen.css'; function ProfileScreen() { const user = useSelector(selectUser); return ( <div className='profileScreen'> <Nav /> <div className="profileScreen__body"> <h1>Edit Profile</h1> <div className="profileScreen__info"> <img src="https://upload.wikimedia.org/wikipedia/commons/0/0b/Netflix-avatar.png" alt="netflix avatar" /> <div className="profileScreen__details"> <h2>{user.email}</h2> <div className="profileScreen__plans"> <button onClick={() => auth.signOut()} className='profileScreen__signOut'>Sign Out</button> </div> </div> </div> </div> </div> ) } export default ProfileScreen;
问题原因
一共三个核心问题导致登录失败、无法跳转:
- 表单默认提交行为冲突:仅给提交按钮绑定
onClick触发登录逻辑,未给<form>标签绑定统一的提交事件,点击按钮时浏览器会触发原生表单提交刷新页面,直接中断Firebase异步登录请求,触发控制台的表单取消报错,用户登录状态根本无法正常写入Redux。 - 缺少登录成功后的主动路由跳转:现有逻辑仅靠Redux用户状态切换渲染分支,登录成功后默认匹配根路径
/,不会自动导航到/profile路径,就算登录成功也只会显示首页,不会进入个人资料页。 - Redux action 写法错误:
dispatch(logout)没有调用action创建函数,退出登录时用户状态无法正确更新。
修复方案
- 把表单提交逻辑统一绑定到
<form>的onSubmit事件上,移除按钮上单独的onClick绑定,彻底阻止默认表单刷新行为。 - 引入
useNavigate路由钩子,注册/登录成功后主动跳转到/profile路径。 - 修正logout的dispatch写法,补全函数调用括号。
具体修改代码
修正App.js中的logout派发逻辑
把原有dispatch(logout);修改为dispatch(logout());,对应useEffect片段:
useEffect(() => { const unsubscribe = auth.onAuthStateChanged((userAuth) => { if (userAuth) { dispatch( login({ uid: userAuth.uid, email: userAuth.email, })) } else { // 修正:logout是action创建函数,需要执行后再dispatch dispatch(logout()); } }); return unsubscribe; },[dispatch]);
修正SignupScreen.js的表单和跳转逻辑
import React, { useRef } from 'react'; import { auth } from '../firebase'; import './SignupScreen.css'; // 新增引入路由导航钩子 import { useNavigate } from 'react-router-dom'; function SignupScreen() { const emailRef = useRef(null); const passwordRef = useRef(null); // 初始化导航方法 const navigate = useNavigate(); const register = (e) => { e.preventDefault(); auth.createUserWithEmailAndPassword( emailRef.current.value, passwordRef.current.value ).then((authUser) => { console.log(authUser); // 注册成功跳转个人页 navigate('/profile'); }) .catch((error) => { alert(error.message); }); }; const signIn = (e) => { e.preventDefault(); auth.signInWithEmailAndPassword( emailRef.current.value, passwordRef.current.value ).then((authUser) => { console.log(authUser); // 登录成功跳转个人页 navigate('/profile'); }) .catch((error) => { alert(error.message); }); }; return ( <div className='signupScreen'> {/* 统一绑定表单提交事件 */} <form onSubmit={signIn}> <h1>Sign In</h1> <input ref={emailRef} placeholder='email' type='email' autoComplete='off' /> <input ref={passwordRef} placeholder='password' type='password' autoComplete='off' /> {/* 提交按钮不需要单独绑定onClick */} <button type='submit'>Sign In</button> <h4> <span className="signupScreen__gray">New to Netflix? </span> {/* 阻止注册点击事件冒泡,避免触发登录提交 */} <span className="signupScreen__link" onClick={(e) => {e.stopPropagation(); register(e);}}> Sign Up now.</span> </h4> </form> </div> ) } export default SignupScreen;
修改完成后,表单不会再触发默认刷新,Firebase登录请求可正常执行,用户状态写入Redux后会自动渲染登录后的路由分支,同时自动导航到个人资料页,不会再停留在登录界面。
内容的提问来源于stack exchange,提问作者Milan Kumar Bura
相关产品推荐
相关产品推荐

