web-dev-qa-db-fra.com

Comment appeler une méthode dans une autre méthode de la classe de réaction Es6

Donc, ce que je suis en train d'essayer de faire est simple

class Something extends React.Component {

validateEmail () {
//code that validates email,innerHTML a div.status element if error occurs
this.removeStatus();//then remove status onkeydown of input element
 }

removeStatus () {
//code that removes the status onkeydown of input element

 }
}

pour une raison quelconque, cela ne fonctionne pas. dans ma console javascript (chrome) Je reçois ce message

login.js:132Uncaught TypeError: this.removeStatus is not a function

Edit 1: J'ai ajouté le code actuel, comme vous pouvez le constater, je lie validateEmail dans le constructeur. 

class Email extends React.Component {
constructor(props) {
      super(props);
      this.change = this.change.bind(this);
      this.validateEmail = this.validateEmail.bind(this);
      this.state = {
        value : ''
      }
    }
removeStatus() {
$('input').on('keydown',function () {
    $('.contextual-info').fadeOut();
});
}

 validateEmail(event) {
event.preventDefault();
var token = $('#token').val();
var email_regex=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
if ($.trim(this.state.value)  !== "") {
    if (email_regex.test(this.state.value)) {
        $.ajax({
            url:'/login',
            type:'post',
            data:{email:this.state.value,_token:token},
            success: function (response) {
            if (response) {
                $('#email').remove();
                $('.btn').remove();
                $('#status').html('');
                ReactDOM.render(<Password /> ,document.getElementById('login-dialogue'));
                $('input[type="password"]').focus();
                }  else {
                $('input#email').addClass('input-context');
                if($('#status').html('<div class="bg-danger contextual-info wrong">Email Address Not Found!</p>')){
                    this.removeStatus();
                    }
                }
            }
        });
    } else {
    if($('#status').html('<div class="bg-danger contextual-info wrong">Invalid Email Address</div>')){
        this.removeStatus();
    }
    }
} else {
    if($('#status').html('<div class="bg-danger contextual-info wrong">Can\'t submit an empty field!</div>')){
        this.removeStatus();
    }
}
}
change (event) {
this.setState({
    value : event.target.value
    });
}

render(){
    return(
        <div className="login-dialogue" id="login-dialogue">
        <h1 className="text-center">Log in</h1>
        <div id="status"></div>
        <form action="" onSubmit={this.validateEmail} id="validateEmail">
        <input type="email" id="email" value={this.state.value} placeholder="Email Address" onChange={this.change} />
        <button type="submit" className="btn btn-flat btn-wide teal white-text">Continue</button>
        </form>
        </div>
        );
}

}
 ReactDOM.render(<Email /> ,document.getElementById('flex-me'));
6
Seun LanLege

Vos méthodes sont correctement définies. Le problème réside donc dans la façon dont vous appelezvalidateEmail.

Vous l'invoquez d'une manière qui définit this sur autre chose que votre instance Something. Ceci est courant chez les auditeurs d'événements. Je suppose que vous avez un code comme celui-ci dans votre render:

<button onClick={this.validateEmail} /> 

La solution recommandée pour React consiste à lier les gestionnaires d’événements de votre constructeur:

class Something extends React.Component {

  constructor() {
    super();
    this.validateEmail = this.validateEmail.bind(this);
  }

  // ...
}

Vous pouvez également appeler la méthode depuis une fonction de flèche, qui conserve la valeur de this à l'endroit où elle a été déclarée:

<button onClick={() => this.validateEmail()} /> 

L'inconvénient de cette approche est qu'un nouveau gestionnaire onClick est créé chaque fois que votre composant est rendu.


EDIT: même problème, endroit différent. Vous appelez removeStatus dans une function, qui perd la liaison this extérieure. Utilisez une fonction de flèche à la place:

$.ajax({
  success: (response) => { 
    // etc
    this.removeStatus();
  }
})

Lectures complémentaires:

13
joews

J'ai eu un problème similaire

Je viens de rencontrer un problème similaire avec le même message d'erreur. Ce qui est étrange, c'est que parfois, lorsque j'appelle une méthode dans une autre méthode, cela fonctionne. Je fais un jeu de Simon et la méthode suivante dans une méthode fonctionne.

handleMouseDown (e) {
    if(e.target.id==="green"){
    $("#green").addClass("colorGreenPush");
      greenSound.play();
      clicked.Push(1);
      this.handleCheck();
    } 

J'exécute simplement une méthode de vérification lorsque l'utilisateur appuie sur un bouton. Pas d'erreur.

Cependant, je recevais un TypeError avec ce code

 handleCheck () {
    var display = $("#display");
    if(litID.length == clicked.length){
      if(litID.join() == clicked.join()){
        if(round == 20){
          setTimeout(function(){
          alert("Unreal. You Acually Won!!!");
          location.reload();
          },1000);
        }
        else{
          setTimeout(function(){
            display.text("-"+(round + 1)+"-");
            round ++;
            console.log(this);
            litID = [];
            clicked = [];
            j = 0;
            this.handleGame();
          },1000);
        }
      } 

Vers la fin, j'essaie this.handleGame(); et cela ne fonctionne pas.

Ma solution

Vous remarquerez que j'ai fait une console.log(this); juste pour voir ce que c'était à ce stade. Il s'avère que c'était l'objet Window. Je ne sais pas pourquoi, peut-être être enterré dans des déclarations if/else. Les deux méthodes sont liées donc ce n'était pas le problème. 

De toute façon. Je suis allé fouiller dans l'objet window et il s'avère que je peux utiliser this.App.prototype.handleGame(); et cela fonctionne! Je devrais ajouter que le nom de mon composant ES6 principal est App. Cela varie en fonction des noms de composant et de méthode, mais le principe général devrait toujours s'appliquer.

 Dev Tools Screenshot

Je suis en état de choc

Je vais admettre que je suis un newb. C'est mon deuxième mini projet dans React, mais le trouver était la chose la plus cool. Maintenant, il peut y avoir d'autres moyens comme les fonctions de flèche mentionnées ci-dessus, mais c'est ce qui a fonctionné pour moi. Et c'était la différence entre avoir un jeu et avoir des ordures droites. J'espère que ça aide quelqu'un.

2
benjaminadk