web-dev-qa-db-ja.com

ReactJs:複数回のボタン押下を防止

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のドキュメントが期待していることです。

クリックされた瞬間にボタンを強制的に無効にしたり、まとめて削除したりするにはどうすればよいですか?

31
Iulius Curt

あなたができることは、クリックされた後にボタンを無効にし、それをページに残します(クリック可能な要素ではありません)。

これを実現するには、ボタン要素に参照を追加する必要があります

<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/

30
eltonkamami

解決策は、ハンドラーに入るとすぐに状態をチェックすることです。 Reactは、インタラクティブイベント(クリックなど)内の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>
21
cquezel

動作するものとしてテスト済み: 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);
16
zvona

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;

使用していることを確認してください^16.7.0-alpha.xバージョンのreactおよびreact-dom

これがあなたを助けることを願っています!

2
slorenzo

必要に応じて、送信を禁止します。

lodash.js debounce

イベント(キーストロークなど)の突然のバーストを1つのイベントにグループ化します。

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

<Button accessible={true}
    onPress={_.debounce(async () => {
                await this.props._selectUserTickets(this.props._accountId)
    }, 1000)}
></Button>
1
Juneho Nam
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
0
Ashok R