You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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创建函数,退出登录时用户状态无法正确更新。

修复方案
  1. 把表单提交逻辑统一绑定到<form>的onSubmit事件上,移除按钮上单独的onClick绑定,彻底阻止默认表单刷新行为。
  2. 引入useNavigate路由钩子,注册/登录成功后主动跳转到/profile路径。
  3. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:45:17