Javascript ReactJs:防止多次按下按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35315872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:34:26  来源:igfitidea点击:

ReactJs: Prevent multiple times button press

javascriptreactjsreact-jsx

提问by Iulius Curt

In my React component I have a button meant to send some data over AJAX when clicked. I need to happen only the first time, i.e. to disable the button after it's first use.

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

How I'm trying to do this:

我如何尝试这样做:

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>
    );
  }

});

What I think happens is the state variable showUploadButtonnot being updated right away, which the React docs says is expected.

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

How could I enforce the button to get disabled or go away all-together the instant it's being clicked?

我怎么能强制按钮在被点击的瞬间被禁用或消失?

采纳答案by eltonkamami

What you could do is make the button disabled after is clicked and leave it in the page (not clickable element).

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

To achieve this you have to add a ref to the button element

为此,您必须向按钮元素添加一个引用

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

and then on the onClickUploadFile function disable the button

然后在 onClickUploadFile 函数上禁用按钮

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

You can then style the disabled button accordingly to give some feedback to the user with

然后,您可以相应地设置禁用按钮的样式,以便向用户提供一些反馈

.btn:disabled{ /* styles go here */}

If needed make sure to reenable it with

如果需要,请确保重新启用它

this.refs.btn.removeAttribute("disabled");

Update:the preferred way of handling refs in React is with a function and not a string.

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

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


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

here is a small example using the code you provided https://jsfiddle.net/69z2wepo/30824/

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

回答by cquezel

The solution is to check the state immediately upon entry to the handler. React guarantees that setState?inside interactive events (such as click) is flushed at browser event boundary. Ref: https://github.com/facebook/react/issues/11171#issuecomment-357945371

解决方案是在进入处理程序时立即检查状态。React 保证 setState?inside 交互事件(例如单击)在浏览器事件边界刷新。参考: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>

回答by Samuli Hakoniemi

Tested as working one: http://codepen.io/zvona/pen/KVbVPQ

测试为工作之一: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);

回答by slorenzo

You can try using React Hooksto set the Component State.

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

import React, { useState } from 'react';

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

export default Button;

Make sure you are using ^16.7.0-alpha.xversion of reactand react-dom.

确保您使用的^16.7.0-alpha.xreact和版本react-dom

Hope this helps you!

希望这对你有帮助!

回答by Vajk Hermecz

If you disable the button during onClick, you basically get this. A clean way of doing this would be:

如果您在 onClick 期间禁用按钮,您基本上会得到这个。一个干净的方法是:

import React, { useState } from 'react';
import Button from '@material-ui/core/Button';

export default function CalmButton(props) {
    const [executing, setExecuting] = useState(false);

    const {
        disabled,
        onClick,
        ...otherProps
    } = props;

    const onRealClick = async (event) => {
        setExecuting(true);
        try {
            await onClick();
        } finally {
            setExecuting(false);
        }
    };

    return (
        <Button
            onClick={onRealClick}
            disabled={executing || disabled}
            {...otherProps}
        />
    )
}

See it in action here: https://codesandbox.io/s/extended-button-that-disabled-itself-during-onclick-execution-mg6z8

在这里查看它的实际效果:https: //codesandbox.io/s/extended-button-that-disabled-itself-during-onclick-execution-mg6z8

We basically extend the Button component with the extra behaviour of being disabled during onClick execution. Steps to do this:

我们基本上使用在 onClick 执行期间禁用的额外行为来扩展 Button 组件。执行此操作的步骤:

  1. Create local state to capture if we are executing
  2. Extract properties we tamper with (disabled, onClick)
  3. Extend onClick operation with setting the execution state
  4. Render the button with our overridden onClick, and extended disabled
  1. 如果我们正在执行,则创建要捕获的本地状态
  2. 提取我们篡改的属性(禁用,onClick)
  3. 通过设置执行状态扩展 onClick 操作
  4. 使用我们覆盖的 onClick 渲染按钮,并禁用扩展

NOTE: You should ensure that the original onClick operation is async aka it is returning a Promise.

注意:您应该确保原始的 onClick 操作是异步的,也就是返回一个 Promise。

回答by Juneho Nam

If you want, just prevent to submit.

如果您愿意,只需阻止提交即可。

How about using lodash.js debounce

怎么用 lodash.js debounce

Grouping a sudden burst of events (like keystrokes) into a single one.

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

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

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

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

回答by Gazowski

By using event.target, you can disabled the clicked button. Use arrow function when you create and call the function onClick. Don't forget to pass the event in parameter.

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

See my codePen

查看我的代码笔

Here is the code:

这是代码:

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);

回答by rudresh solanki

You can get the element reference in the onClick callback and setAttributefrom there, eg:

您可以在 onClick 回调中获取元素引用,然后setAttribute从那里获取,例如:

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

回答by Ashok R

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();

output

输出

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