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

React中HTTP请求执行期间如何正确禁用表格内按钮?

问题原因

代码失效是两个核心错误导致的:

  • 渲染阶段直接执行异步请求:React渲染函数是同步执行的,每次组件重渲染都会重复触发请求,且async函数返回值永远是Promise对象,Boolean(Promise)固定为true,根本拿不到你预期的布尔判断结果
  • 原生axios调用写法错误:axios.get()本身返回Promise,不会直接返回loading/error/data这类响应式字段,这是React Query、SWR等第三方请求库的返回格式,直接解构拿值拿到的全是undefined
可行实现

原生React+axios实现(无额外依赖)

把请求逻辑放到副作用钩子中,用组件状态持久化存储请求结果,不要在JSX里直接发请求:

import { useState, useEffect } from 'react'
import axios from 'axios'
// 替换成你实际用的Table、Button组件引入路径
import { Table, Button } from 'antd'

function BusinessTable() {
  const [buttonStatus, setButtonStatus] = useState({})
  const [statusLoading, setStatusLoading] = useState(true)

  // 组件挂载/依赖参数变化时拉取按钮状态
  useEffect(() => {
    const getStatus = async () => {
      setStatusLoading(true)
      try {
        // 优先批量拉取所有行的状态,避免逐行发请求产生性能问题
        const { data } = await axios.get(API, { params: payload })
        // 按行唯一ID组装状态映射,方便渲染时直接取值
        const statusMap = {}
        data.forEach(item => {
          statusMap[item.rowId] = item.length > 0
        })
        setButtonStatus(statusMap)
      } catch (err) {
        console.error('按钮状态拉取失败', err)
        // 错误场景可配置兜底逻辑,比如默认禁用按钮避免误操作
      } finally {
        setStatusLoading(false)
      }
    }

    getStatus()
  }, [payload])

  const DoSomething = (rowData) => {
    // 按钮点击的业务逻辑
  }

  return (
    <Table>
      <tbody>
        {tableData.map(row => (
          <tr key={row.id}>
            <td>{row.field1}</td>
            <td>{row.field2}</td>
            <td>{row.field3}</td>
            <td>
              <Button
                onClick={() => DoSomething(row)}
                disabled={statusLoading || buttonStatus[row.id]}
              >
                Click me!
              </Button>
            </td>
          </tr>
        ))}
      </tbody>
    </Table>
  )
}

简化实现(带缓存/重试需求可用)

如果表格数据量大、需要请求缓存、自动重试能力,可以用SWR或React Query这类成熟请求库,不需要自己手写维护loading、重试、缓存逻辑,示例用SWR:

import useSWR from 'swr'
import axios from 'axios'

function BusinessTable() {
  const { data: buttonStatus, isLoading: statusLoading } = useSWR(
    [API, payload],
    ([url, params]) => axios.get(url, { params }).then(res => res.data),
    { revalidateOnFocus: false }
  )

  // 渲染逻辑和上面的原生实现一致
}
避坑点
  • 不要在JSX的属性表达式里直接写异步函数调用:渲染过程必须是无副作用的纯操作,异步返回的Promise不能直接作为布尔判断值
  • 优先批量拉取全表的按钮状态,逐行单独发请求会产生大量重复请求,拖慢页面加载速度
  • 状态加载过程中默认禁用按钮,避免状态未就绪时用户点击触发不符合预期的操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:57:24