React表单提交时MUI LoadingButton禁用状态不生效问题排查
问题诊断
你的Sign In按钮无法进入禁用加载状态的核心错误出在fetch请求的Promise链式调用写法上:
.then(setLoading(false))
这行代码没有把setLoading(false)作为.then()的回调函数传入,而是在Promise链创建的瞬间就直接执行了setLoading(false)。代码实际运行顺序是:
- 执行
setLoading(true)尝试把按钮设为加载态 - 发起fetch请求
- 立刻同步执行
setLoading(false)把加载态重置,完全不会等待接口返回
这就导致loading状态刚被设为true就被立刻覆盖,哪怕接口请求耗时再长,按钮也不会显示加载状态。
除此之外代码还有一处遗漏:接口请求抛错进入catch分支时,没有重置loading状态,会导致请求失败后按钮永久卡在加载态。
修复方法
- 把
.then()中直接执行的状态重置逻辑改为回调形式,确保等待前面的Promise执行完成后再修改状态 - 在请求结束的所有分支(成功/失败)都补充
setLoading(false)逻辑,避免状态异常 - (可选优化)移除冗余的
onSubmit包装函数,直接将handleSubmit绑定给表单提交事件即可
修复后的核心提交逻辑代码如下:
async function handleSubmit(e) { e.preventDefault(); if (!emailRef.current.value) { return setError('Please enter an Email Address'); } if (!passwordRef.current.value) { return setError('Please enter a password'); } setLoading(true); setError(''); try { const response = await fetch( `${process.env.REACT_APP_API_URL}auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ Email: emailRef.current.value, Password: passwordRef.current.value, }), }, ) if (response.ok) { auth.signin(emailRef.current.value); return navigate('/Dashboard'); } const errorText = await response.json(); throw new Error(errorText.message); } catch (err) { setError(err.message); } finally { // 无论请求成功还是失败,最终都重置加载状态 setLoading(false); } }
对应的表单绑定可以直接简化为:
<form onSubmit={handleSubmit}>
用async/await+try/catch/finally的写法比原始Promise链式调用更直观,也能避免出现漏写回调、状态重置遗漏的问题。
内容的提问来源于stack exchange,提问作者Kelden Mayer
相关产品推荐
相关产品推荐

