ReactJs:防止多次按下按钮

时间:2016-02-10 12:54:19

标签: javascript reactjs react-jsx

在我的React组件中,我有一个按钮,用于在单击时通过AJAX发送一些数据。我只需要第一次发生,即在第一次使用后禁用按钮。

我是如何尝试这样做的:

var UploadArea = React.createClass({

  getInitialState() {
    return {
      showUploadButton: true
    };
  },

  disableUploadButton(callback) {
    this.setState({ showUploadButton: false }, callback);
  },

  // This was simpler before I started trying everything I could think of
  onClickUploadFile() {
    if (!this.state.showUploadButton) {
      return;
    }
    this.disableUploadButton(function() {
      $.ajax({
        [...]
      });

    });
  },

  render() {
    var uploadButton;
    if (this.state.showUploadButton) {
      uploadButton = (
        <button onClick={this.onClickUploadFile}>Send</button>
      );
    }

    return (
      <div>
        {uploadButton}
      </div>
    );
  }

});

我认为发生的是状态变量showUploadButton没有立即更新,React文档说的是预期的。

我如何强制按钮被禁用或在点击它的瞬间全部消失?

9 个答案:

答案 0 :(得分:28)

您可以执行的操作是在单击按钮后将其禁用并将其保留在页面中(不是可单击的元素)。

要实现这一点,您必须为按钮元素添加引用

<button ref="btn" onClick={this.onClickUploadFile}>Send</button>

然后在onClickUploadFile函数上禁用按钮

this.refs.btn.setAttribute("disabled", "disabled");

然后,您可以相应地设置禁用按钮的样式,以便通过

向用户提供一些反馈
.btn:disabled{ /* styles go here */}

如果需要,请务必使用

重新启用它
this.refs.btn.removeAttribute("disabled");

更新:在React中处理引用的首选方法是使用函数而不是字符串。

<button 
  ref={btn => { this.btn = btn; }} 
  onClick={this.onClickUploadFile}
>Send</button>


this.btn.setAttribute("disabled", "disabled");
this.btn.removeAttribute("disabled");

这是使用您提供的代码的一个小例子 https://jsfiddle.net/69z2wepo/30824/

答案 1 :(得分:19)

解决方案是在进入处理程序后立即检查状态。 React保证在浏览器事件边界刷新交互事件(例如click)中的setState。参考:https://github.com/facebook/react/issues/11171#issuecomment-357945371

// In constructor
this.state = {
    disabled : false
};


// Handler for on click
handleClick = (event) => {
    if (this.state.disabled) {
        return;
    }
    this.setState({disabled: true});
    // Send     
}

// In render
<button onClick={this.handleClick} disabled={this.state.disabled} ...>
    {this.state.disabled ? 'Sending...' : 'Send'}
<button>

答案 2 :(得分:14)

经过测试:http://codepen.io/zvona/pen/KVbVPQ

class UploadArea extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      isButtonDisabled: false
    }
  }

  uploadFile() {
    // first set the isButtonDisabled to true
    this.setState({
      isButtonDisabled: true
    });
    // then do your thing
  }

  render() {
    return (
      <button
        type='submit'
        onClick={() => this.uploadFile()}
        disabled={this.state.isButtonDisabled}>
        Upload
      </button>
    )
  }
}

ReactDOM.render(<UploadArea />, document.body);

答案 3 :(得分:2)

您可以尝试使用React Hooks来设置Component State

import React, { setState } from 'react';

const Button = () => {
  const [double, setDouble] = setState(false);
  return (
    <button
      disabled={double}
      onClick={() => {
        // doSomething();
        setDouble(true);
      }}
    />
  );
};

export default Button;

确保使用^16.7.0-alpha.xreact的{​​{1}}版。

希望这对您有帮助!

答案 4 :(得分:0)

如果需要,只需阻止提交即可。

如何使用lodash.js debounce

将突发事件(如击键)分组为一个事件。

https://lodash.com/docs/4.17.11#debounce

<Button accessible={true}
    onPress={_.debounce(async () => {
                await this.props._selectUserTickets(this.props._accountId)
    }, 1000)}
></Button>

答案 5 :(得分:0)

const once = (f, g) => {
    let done = false;
    return (...args) => {
        if (!done) {
            done = true;
            f(...args);
        } else {
            g(...args);
        }
    };
};

const exampleMethod = () => console.log("exampleMethod executed for the first time");
const errorMethod = () => console.log("exampleMethod can be executed only once")

let onlyOnce = once(exampleMethod, errorMethod);
onlyOnce();
onlyOnce();

输出

exampleMethod executed for the first time
exampleMethod can be executed only once

答案 6 :(得分:0)

使用event.target可以禁用单击的按钮。 创建并调用函数onClick时,请使用箭头函数。不要忘记在参数中传递事件。

看到我的codePen

代码如下:

class Buttons extends React.Component{
  constructor(props){
    super(props)
    this.buttons = ['A','B','C','D']
  }

  disableOnclick = (e) =>{
    e.target.disabled = true
  }

  render(){
    return(

     <div>
        {this.buttons.map((btn,index) => (
          <button type='button' 
            key={index} 
            onClick={(e)=>this.disableOnclick(e)}
            >{btn}</button>
        ))}
      </div>
  )}

}
ReactDOM.render(<Buttons />, document.body);

答案 7 :(得分:0)

您可以在onClick回调和setAttribute中获得元素引用,例如:

      <Button
        onClick={(e) => {
          e.target.setAttribute("disabled", true);
          this.handler();
        }}            
      >
        Submit
      </Button>

答案 8 :(得分:0)

保持简单和内联:

<button type="submit"
        onClick={event => event.currentTarget.disabled = true}>
    save
</button>

但是!当表单校准失败时,这也将禁用该按钮!所以您将无法重新提交。

在这种情况下,setter 更好。

此修复此设置禁用 onSubmit 形式:


// state variable if the form is currently submitting
const [submitting, setSubmitting] = useState(false);

// ...
return (
<form onSubmit={e => {
                setSubmitting(true); // create a method to modify the element
            }}>

    <SubmitButton showLoading={submitting}>save</SubmitButton>
</form>
);

按钮看起来像这样:

import {ReactComponent as IconCog} from '../../img/icon/cog.svg';
import {useEffect, useRef} from "react";

export const SubmitButton = ({children, showLoading}) => {

    const submitButton = useRef();

    useEffect(() => {
        if (showLoading) {
            submitButton.current.disabled = true;
        } else {
            submitButton.current.removeAttribute("disabled");
        }
    }, [showLoading]);

    return (
        <button type="submit"
                ref={submitButton}>
            <main>
                <span>{children}</span>
            </main>
        </button>
    );

};