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

React中如何在onClick执行期间禁用按钮并自动恢复?

解决React遗留应用中按钮重复点击的问题

问题分析

当前代码的核心问题是耗时的同步操作阻塞了React渲染线程,导致btnLock状态更新后,Button组件无法及时重新渲染,依然会接收点击事件并排队执行。另外,await setState是错误用法——setState不返回Promise,无法通过await等待状态更新完成。

解决方案

需要做两处关键修改:

  • 将耗时操作转为异步执行,释放主线程让React能及时更新UI
  • 在Button组件中通过disabled属性从DOM层面禁用按钮,配合状态判断实现双重拦截

修改后的App组件代码

import "./App.css";
import React, { Component } from "react";
import Button from "./components/button";

class App extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    this.state = {
      counter: 0,
      btnLock: false,
    };
  }

  async handleClick() {
    // 立即锁定按钮
    this.setState({ 
      counter: this.state.counter + 1, 
      btnLock: true 
    });

    try {
      // 将耗时操作包装为Promise,放到异步队列执行,不阻塞主线程
      await new Promise(resolve => {
        var i = 0;
        var text;
        while (i < 20000000) {
          text = "The number is " + i;
          i++;
        }
        resolve();
      });

      console.log("click" + this.state.counter);
    } finally {
      // 无论操作成功失败,最终都解锁按钮
      this.setState({ btnLock: false });
    }
  };

  render() {
    return <Button 
      handleClick={this.handleClick}
      btnLock={this.state.btnLock}
    />;
  }
}

export default App;

修改后的Button组件代码

import React, { Component } from "react";

class Button extends Component {
  constructor(props){
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    // 状态层面拦截重复点击
    if (!this.props.btnLock) {
      this.props.handleClick();
    }
  };

  render() {
    // DOM层面禁用按钮,用户连点击事件都触发不了
    return <button 
      onClick={this.handleClick}
      disabled={this.props.btnLock}
    >BUTTON</button>;
  }
}

export default Button;

关键说明

  1. 异步耗时操作:把同步循环放到Promise中,通过await等待完成,这样不会阻塞主线程,React能及时更新btnLock状态并重新渲染Button组件。
  2. 双重拦截机制:
    • DOM层面的disabled属性直接让按钮无法被点击,从根源阻止事件触发
    • 状态判断作为兜底,即使DOM禁用失效,也不会执行重复的处理函数
  3. finally解锁:用try/finally确保无论耗时操作成功还是失败,按钮最终都会解锁,避免出现永久禁用的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:16:11