Firebase sendPasswordResetEmail的then导航失效,提交后自动跳转首页
忘记密码页面导航失效且自动跳首页问题
我搭建了一个基础的忘记密码页面,正在实现Firebase的sendPasswordResetEmail功能。该功能可正常触发,但在成功回调(then)中添加navigate导航功能时无法生效。无论操作成功或失败,提交后页面都会自动跳转到首页,URL末尾带有“?”,请问这是什么原因?
原代码
import React, { useState } from "react"; import { useNavigate } from 'react-router-dom'; import { getAuth, sendPasswordResetEmail } from "firebase/auth"; import '../scss/pages/ForgotPage.scss' function ForgotPassword() { document.title = 'Acquired | Forgot Password'; const navigate = useNavigate(); const navigateTo = (path) => { navigate(path) } const [email, setEmail] = useState('') const auth = getAuth(); const forgotPassword = (Email) => { sendPasswordResetEmail(auth, Email) .then(function () { console.log('success'); }).catch((error) => { const errorCode = error.code; const errorMessage = error.message; console.log(errorMessage); }); } return ( <div className='pageBackground'> <div className='loginContainer'> <div className="regForm-container sign-in-container"> <form className='regForm' action="/"> <h1 className='formHeader'>Enter your login email</h1> <input className='loginInput' type="email" placeholder="Email" onChange={(a) => setEmail(a.target.value)} value={email} required /> <button className='ghost' onClick={() => forgotPassword(email)}>Reset</button> </form> </div> <div className="overlay-container"> <div className="overlay"> <div className="overlay-panel overlay-right"> <h1 className='formHeader'>Don't sweat it</h1> <h5 className='regP'>Forgetting a password happens to the best of us!</h5> <h5 className='regP'>But just in case you remembered</h5> <button className='ghostOther' onClick={() => navigate('/signin')}>Log In</button> </div> </div> </div> </div> </div> ) } export default ForgotPassword;
问题原因
核心问题是表单的默认提交行为:
- 按钮放在
<form>标签内,默认类型为submit,点击后会触发表单的默认提交动作 - 表单设置了
action="/",提交后会直接跳转到首页;URL末尾的?是表单默认以GET方式提交的特征(未指定method时默认用GET) - 浏览器的同步跳转行为会直接中断回调里的异步导航逻辑,导致
navigate根本没机会生效
解决办法(两种任选其一)
方法1:阻止按钮点击的默认行为
修改forgotPassword函数,接收事件对象并阻止默认提交:
const forgotPassword = (e, Email) => { e.preventDefault(); // 阻止表单默认提交 sendPasswordResetEmail(auth, Email) .then(function () { console.log('success'); navigate('/signin'); // 导航可正常生效 }).catch((error) => { const errorCode = error.code; const errorMessage = error.message; console.log(errorMessage); }); }
同时修改按钮点击事件,传入事件对象:
<button className='ghost' onClick={(e) => forgotPassword(e, email)}>Reset</button>
方法2:将按钮设为非提交类型
给按钮添加type="button",避免触发表单提交:
<button className='ghost' type="button" onClick={() => forgotPassword(email)}>Reset</button>
同时可以去掉表单的action="/",因为不再需要默认提交行为:
<form className='regForm'>
修改后的完整代码示例(以方法2为例)
import React, { useState } from "react"; import { useNavigate } from 'react-router-dom'; import { getAuth, sendPasswordResetEmail } from "firebase/auth"; import '../scss/pages/ForgotPage.scss' function ForgotPassword() { document.title = 'Acquired | Forgot Password'; const navigate = useNavigate(); const [email, setEmail] = useState('') const auth = getAuth(); const forgotPassword = (Email) => { sendPasswordResetEmail(auth, Email) .then(function () { console.log('success'); navigate('/signin'); // 导航正常执行 }).catch((error) => { const errorCode = error.code; const errorMessage = error.message; console.log(errorMessage); }); } return ( <div className='pageBackground'> <div className='loginContainer'> <div className="regForm-container sign-in-container"> <form className='regForm'> <h1 className='formHeader'>Enter your login email</h1> <input className='loginInput' type="email" placeholder="Email" onChange={(a) => setEmail(a.target.value)} value={email} required /> <button className='ghost' type="button" onClick={() => forgotPassword(email)}>Reset</button> </form> </div> <div className="overlay-container"> <div className="overlay"> <div className="overlay-panel overlay-right"> <h1 className='formHeader'>Don't sweat it</h1> <h5 className='regP'>Forgetting a password happens to the best of us!</h5> <h5 className='regP'>But just in case you remembered</h5> <button className='ghostOther' onClick={() => navigate('/signin')}>Log In</button> </div> </div> </div> </div> </div> ) } export default ForgotPassword;
内容的提问来源于stack exchange,提问作者Christopher Koziol
相关产品推荐
相关产品推荐

