React中fetch请求数据期间如何设置按钮为加载禁用状态
实现方案
你的核心诉求是接口请求完成(返回200状态码)前按钮保持加载禁用状态,阻止用户提前跳转,现有代码已经有loading状态的切换逻辑,缺的是状态的正确暴露和边界场景处理,按下面步骤改即可:
1. 修正自定义Hook,暴露可消费的状态
首先把你写的postData方法包在自定义Hook里,把loading、error状态和提交方法一起返回,同时修正原代码的语法错误、补全边界处理:
import { useState, useCallback } from 'react' import axios from 'axios' function useSubmitAction() { const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const postData = useCallback(async (formData) => { setError(null) setLoading(true) try { const res = await axios({ url: '替换为你的实际接口地址', headers: {}, // 替换为实际请求头配置 method: 'POST', // 替换为实际请求方法 data: formData, // 传入下拉框选中的提交值 responseType: 'json' // 替换为实际需要的响应类型 }) // 显式校验200状态码,避免后端返回其他2xx状态码时提前放行 if (res.status !== 200) throw new Error(`请求异常,状态码:${res.status}`) return res.data } catch (err) { setError(err.response?.data || err.message) throw err } finally { // 无论成功失败,请求结束统一关闭loading,避免漏写导致按钮卡死 setLoading(false) } }, []) return { loading, error, postData } } export default useSubmitAction
2. 组件层绑定状态到按钮
在业务组件里引入上面的Hook,直接把返回的loading绑定到按钮属性上即可,注意跳转逻辑必须等await请求 resolve 之后再执行,从流程上杜绝提前跳页:
import { useState } from 'react' import { Button, Select, message } from 'antd' // 按你实际使用的组件库引入 import useSubmitAction from './useSubmitAction' export default function FormPage() { const [selected, setSelected] = useState() const { loading, error, postData } = useSubmitAction() const handleClick = async () => { if (!selected) return message.warning('请先选择下拉选项') try { await postData({ selectedValue: selected }) // 只有请求成功返回200,才会走到下面的跳转逻辑 message.success('提交成功') // 此处写你的下一页跳转逻辑,比如 router.push('/next-step') } catch (err) { console.error('提交失败', err) } } return ( <div> <Select value={selected} onChange={setSelected} disabled={loading} placeholder="请选择选项" style={{ width: 240, marginBottom: 16 }} options={/* 你的下拉选项配置 */} /> <Button type="primary" onClick={handleClick} loading={loading} disabled={loading || !selected} > 继续 </Button> {error && <div style={{ color: '#ff4d4f', marginTop: 8 }}>提交失败:{typeof error === 'string' ? error : JSON.stringify(error)}</div>} </div> ) }
关键注意点
- 不要把跳转逻辑写在请求调用的外层,必须等
await postData()执行完成、确认接口返回200之后再触发跳转,从流程上堵死提前跳页的可能 - 请求过程中建议把下拉选择框也设为禁用,避免用户在请求发起后修改选中值,导致提交数据和用户最终选择不一致
- 原代码catch块里
setError(error.response.data));多写了一个右括号,直接运行会报语法错误,需要删除 - 如果用的是原生button组件,除了加loading样式,必须显式写
disabled={loading},原生按钮没有自带的loading禁用逻辑
内容的提问来源于stack exchange,提问作者ERLay
相关产品推荐
相关产品推荐

