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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:51:17