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

React中API请求进行时如何禁用登录按钮?

解决React登录按钮重复提交(请求中禁用)的问题

你的思路其实是对的——用state管理按钮的加载状态,但大概率是没在正确的时机更新状态,或者漏掉了错误场景的状态重置。我来帮你调整代码,完美实现这个功能:

修改步骤

  1. 添加loading状态:用来标记当前是否正在发起登录请求
  2. 请求前激活loading:表单验证通过后,立刻把loading设为true,禁用按钮
  3. 请求结束后重置loading:用finally块确保不管请求成功还是失败,都把loading改回false,恢复按钮可用
  4. 给按钮绑定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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:12:33