React中API请求进行时如何禁用登录按钮?
解决React登录按钮重复提交(请求中禁用)的问题
你的思路其实是对的——用state管理按钮的加载状态,但大概率是没在正确的时机更新状态,或者漏掉了错误场景的状态重置。我来帮你调整代码,完美实现这个功能:
修改步骤
- 添加loading状态:用来标记当前是否正在发起登录请求
- 请求前激活loading:表单验证通过后,立刻把loading设为
true,禁用按钮 - 请求结束后重置loading:用
finally块确保不管请求成功还是失败,都把loading改回false,恢复按钮可用 - 给按钮绑定disabled属性:把loading状态和按钮的禁用状态关联起来
修改后的完整代码
import api from '../services/api' import { useState } from 'react' import { Link, useNavigate } from 'react-router-dom' import { validateFormDataForLogin } from '../validate' export default function LoginPage() { // form state const [formData, setFormData] = useState({ 'email': '', 'password': '', }) // 新增:管理按钮加载状态,初始为false const [isLoading, setIsLoading] = useState(false) // using navigate const navigate = useNavigate() // function to handle the changes function handleChange(e) { const { name, value } = e.target setFormData(prevFormData => ({ ...prevFormData, [name]: value, })) } // function to handle the submit async function handleSubmit(e) { e.preventDefault() const errorMessage = validateFormDataForLogin(formData) if (errorMessage) { alert(errorMessage) return } // 表单验证通过后,立即设置loading为true,禁用按钮 setIsLoading(true) try { await api.post('/api/user/login', { email: formData.email, password: formData.password, }) navigate('/dashboard', { replace: true, }) } catch (error) { if (error.response) { alert(error.response.data.message) } } finally { // 不管请求成功/失败,最终都重置loading状态,恢复按钮 setIsLoading(false) } } return ( <div className='login'> <h1 className='login--title'>Login</h1> <div className='login--content'> <form className='login--form' onSubmit={handleSubmit}> <input type='text' className='login--form--input' placeholder='Email address' name='email' value={formData.email} onChange={handleChange} /> <input type='password' className='login--form--input' placeholder='Password' name='password' value={formData.password} onChange={handleChange} /> <p className='login--form--forgot_password'>Forgot Password</p> {/* 给按钮添加disabled属性,绑定isLoading状态,同时优化按钮文本提示 */} <input className='login--form--submit' type='submit' value={isLoading ? 'LOGGING IN...' : 'LOGIN'} disabled={isLoading} /> </form> <div className='login--row'> <span className='login--row--text'>Don't have an account?</span> <Link to='/register' className='login--row--link'>Register</Link> </div> </div> </div> ) }
为什么你的原方案没生效?
大概率是这两个原因之一:
- 没有给按钮添加
disabled={isLoading}属性,状态变化了但按钮没有响应 - 没在
catch块或者finally里重置loading状态,如果请求失败,loading会一直是true,按钮永远处于禁用状态
这样修改后,用户点击登录按钮后,按钮会立刻变成禁用状态,同时文本更新为“LOGGING IN...”(可选优化),等请求完成(不管成功失败),按钮都会恢复可用,完美避免重复提交~
内容的提问来源于stack exchange,提问作者dipansh
相关产品推荐
相关产品推荐

