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

React注册页面提交按钮无法禁用的问题排查

注册提交按钮无法禁用问题

问题现象

  • 在按钮组件上设置disabled={loading}属性不生效
  • 尝试创建常量isDisabled=true模拟禁用样式,但样式无法动态切换,点击提交时按钮仍不会变为禁用状态

原代码

import styles, {layout} from '../style';
import {eye, eye_hidden, google} from "../assets";
import {useState, useRef} from 'react';
import {useAuth} from '../contexts/AuthContext';

const SignUp = () => {
    const {signup, currentUser} = useAuth()

    const nameRef = useRef()
    const emailRef = useRef()
    const emailConfRef = useRef()
    const pwRef = useRef()
    const pwConfRef = useRef()

    const [error, setError] = useState("")
    const [loading, setLoading] = useState(false)
    const [visibility_pw, setVisibility_pw] = useState(false)
    const [visibility_pwConf, setVisibility_pwConf] = useState(false)

    const handleVisibility = param => event => {
        param === "pw" ? setVisibility_pw(!visibility_pw) : setVisibility_pwConf(!visibility_pwConf)
    }

    async function handleSubmit(event) {
        event.preventDefault()

        if (pwRef.current.value !== pwConfRef.current.value) {
            return setError('Passwords or Emails do not match. Please try again.')
        }

        if (emailRef.current.value !== emailConfRef.current.value) {
            return setError('Emails do not match!')
        }
        try {
            setError('')
            setLoading(true)
            signup(emailRef.current.value, pwRef.current.value)
        } catch(error) {
            console.log(error.message)
            setError('Unable to create account. Please try again')
        }
        setLoading(false)
    }

    return (
        <div className={`${layout.sectionCenter} min-h-screen`}>
            <div className="bg-black/25 shadow-xl shadow-[#8F6E5D]/40 rounded-2xl p-5 min-h-full xs:w-full max-w-[800px]">
                <h2 className={`text-center mt-8 ${styles.heading4}`}>Create A New Account</h2>
                {error && 
                <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mx-8 mt-8" role="alert">
                    <strong className="block sm:inline font-bold">{error}</strong>
                </div>}
                {currentUser && currentUser.email}
                <form action="" onSubmit={handleSubmit} className="flex flex-col px-8 gap-8 mt-12">
                    <input required type="text" name="name" id="name" ref={nameRef} placeholder="Enter Full Name" className="pl-2 py-2.5 rounded-lg border border-[#8F6E5D] border-opacity-75 bg-primary text-secondary" />
                    <input required type="email" name="email" id="email" ref={emailRef} placeholder="Enter Email" className="pl-2 py-2.5 rounded-lg border border-[#8F6E5D] border-opacity-75 bg-primary text-secondary" />
                    <input required type="email" name="email_conf" id="email_conf" ref={emailConfRef} placeholder="Confirm Email" className="pl-2 py-2.5 rounded-lg border border-[#8F6E5D] border-opacity-75 bg-primary text-secondary" />
                    <div className="relative">
                        <input required type={visibility_pw ? "text" : "password"} name="password" id="password" ref={pwRef} placeholder="Enter Password" className="pl-2 py-2.5 rounded-lg border border-[#8F6E5D] border-opacity-75 bg-primary w-full text-secondary" />
                        <img onClick={handleVisibility("pw")} src={visibility_pw ? eye_hidden : eye} alt="toggle password visibility" className={`${visibility_pw ? "h-[20px]" : "h-[65%]"} pw_visibility absolute top-[50%] right-5 -translate-y-[50%] cursor-pointer`} />
                    </div>
                    <div className="relative">
                        <input required type={visibility_pwConf ? "text" : "password"} name="password_conf" id="password_conf" ref={pwConfRef} placeholder="Confirm Password" className="pl-2 py-2.5 rounded-lg border border-[#8F6E5D] border-opacity-75 bg-primary w-full text-secondary" />
                        <img onClick={handleVisibility("pw_conf")} src={visibility_pwConf ? eye_hidden : eye} alt="toggle confirm password visibility" className={`${visibility_pwConf ? "h-[20px]" : "h-[65%]"} pw_visibility absolute top-[50%] right-5 -translate-y-[50%] cursor-pointer`} />
                    </div>
                    <button disabled={loading} type="submit" className={`py-2 px-6 font-playfairDisplay font-medium text-[18px] outline-none rounded-lg ${loading ? "bg-gradient-to-r from-[#8F6E5D]/50 to-[#7E4F43]/50 text-dimWhite/50" : "bg-gradient-to-r from-[#8F6E5D] to-[#7E4F43] text-white"} ${loading ? "" : styles.buttonHover} mx-auto mt-4`}>Sign Up</button>
                </form>
                <div className="mt-12 grid grid-cols-3 px-8 items-center">
                    <hr className="opacity-25"/>
                    <p className={`${styles.paragraph} text-center text-md`}>OR</p>
                    <hr className="opacity-25"/>
                </div>
                <button type="button" className="bg-white border py-2 px-4 mt-8 mb-12 mx-auto rounded-lg flex justify-center items-center text-center hover:scale-95 duration-300">
                    <img src={google} alt="google icon" className="h-[32px] w-[32px]" />
                    <p className="ml-3">Sign up with Google</p>
                </button>
                <div className="flex justify-between px-8 mt-4 mb-8">
                    <p className={`${styles.paragraph} text-sm sm:text-lg`}>Have an account?</p>
                    <button type="button" className="hover:scale-90 duration-300 hover:text-[#8F6E5D] hover:from-[#FAF6F5] hover:to-[#FAF6F5] hover:ease-in-out cursor-pointer py-1 px-2 bg-gradient-to-r from-[#8F6E5D] to-[#7E4F43] font-playfairDisplay font-medium text-[18px] text-white outline-none rounded-lg">Login</button>
                </div>
            </div>
        </div>
    )
}

export default SignUp

尝试的修改代码

<button disabled={loading} type="submit" className={`py-2 px-6 font-playfairDisplay font-medium text-[18px] outline-none rounded-lg ${isDisabled ? "bg-gradient-to-r from-[#8F6E5D]/50 to-[#7E4F43]/50 text-dimWhite/50" : "bg-gradient-to-r from-[#8F6E5D] to-[#7E4F43] text-white"} ${isDisabled ? "" : styles.buttonHover} mx-auto mt-4`}>Sign Up</button>

解决方案

问题核心在于handleSubmit函数中,异步操作signup未等待完成就直接执行setLoading(false),导致loading状态刚设为true就立刻变回false,按钮无法保持禁用状态。同时,常量isDisabled的值不会随状态变化,无法实现动态样式切换。

修改handleSubmit函数,添加await等待signup完成,并将setLoading(false)放入finally块确保无论操作成功或失败都会执行:

async function handleSubmit(event) {
    event.preventDefault()

    if (pwRef.current.value !== pwConfRef.current.value) {
        return setError('Passwords or Emails do not match. Please try again.')
    }

    if (emailRef.current.value !== emailConfRef.current.value) {
        return setError('Emails do not match!')
    }
    try {
        setError('')
        setLoading(true)
        await signup(emailRef.current.value, pwRef.current.value) // 等待异步注册完成
    } catch(error) {
        console.log(error.message)
        setError('Unable to create account. Please try again')
    } finally {
        setLoading(false) // 无论成功失败都重置loading状态
    }
}

同时保持按钮的disabled={loading}和用loading状态控制样式的逻辑,无需使用常量isDisabled:

<button disabled={loading} type="submit" className={`py-2 px-6 font-playfairDisplay font-medium text-[18px] outline-none rounded-lg ${loading ? "bg-gradient-to-r from-[#8F6E5D]/50 to-[#7E4F43]/50 text-dimWhite/50" : "bg-gradient-to-r from-[#8F6E5D] to-[#7E4F43] text-white"} ${loading ? "" : styles.buttonHover} mx-auto mt-4`}>Sign Up</button>

修改后,点击提交按钮时loading变为true,按钮进入禁用状态并切换样式;等待注册操作完成后,loading变回false,按钮恢复可用状态。

内容的提问来源于stack exchange,提问作者Ramana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:02:05