web-dev-qa-db-fra.com

ReactJs: Empêcher plusieurs fois d'appuyer sur le bouton

Dans mon composant React, j'ai un bouton destiné à envoyer des données via AJAX lorsque l'utilisateur clique dessus. Je n'ai besoin que de la première fois, c'est-à-dire de désactiver le bouton après sa première utilisation.

Comment j'essaye de faire ceci:

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

});

Je pense que ce qui se passe, c’est que la variable d’état showUploadButton ne soit pas mise à jour immédiatement, ce que la documentation de React dit est prévue.

Comment puis-je imposer le bouton pour être désactivé ou partir tout de suite dès que l'utilisateur clique dessus?

21
Iulius Curt

Ce que vous pouvez faire est de rendre le bouton désactivé après avoir cliqué et de le laisser dans la page (élément non cliquable).

Pour ce faire, vous devez ajouter une référence à l'élément button.

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

puis sur la fonction onClickUploadFile désactiver le bouton

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

Vous pouvez ensuite styler le bouton désactivé en conséquence pour donner un retour à l'utilisateur avec

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

Si nécessaire, assurez-vous de le réactiver avec

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

Update: le moyen privilégié de gérer les références dans React consiste à utiliser une fonction et non une chaîne.

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


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

voici un petit exemple utilisant le code que vous avez fourni https://jsfiddle.net/69z2wepo/30824/

24
eltonkamami

Testé comme fonctionnant: 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);
15
zvona

La solution consiste à vérifier l'état immédiatement après son entrée dans le gestionnaire. React garantit que setState dans les événements interactifs (tels que click) est vidé à la limite des événements du navigateur. Ref: 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>
11
cquezel

Vous pouvez essayer d’utiliser React Hooks pour définir l’état Component .

import React, { setState } from 'react';

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

export default Button;

Assurez-vous que vous utilisez la version ^16.7.0-alpha.x de react et react-dom.

J'espère que cela vous aide!

0
slorenzo

Si vous voulez, empêchez simplement de soumettre.

Que diriez-vous d'utiliser lodash.js debounce 

Regrouper une rafale soudaine d'événements (comme des frappes au clavier) en un seul.

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

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