1
votes

Le gestionnaire d'événements React fonctionne sans bind ()

Je travaille sur un didacticiel de réaction et l'instructeur montre que le gestionnaire d'événements dans ce code ne fonctionnera pas, car this () accède à l'environnement externe. Mais je n'obtiens aucune erreur. Quelqu'un peut-il me l'expliquer?

import React, { Component } from "react";

class Counter extends Component {
  state = {
    count: 0,
  };

  handleIncrement() {
    console.log(this.state);
    console.log(this.props);
  }

  render() {
    return (
      <div>
        <button onClick={this.handleIncrement()}>
          Increment
        </button>
      </div>
    );
  }
}

export default Counter;


5 commentaires

Bienvenue dans Stack Overflow Benedikt! Vous invoquez this.handleIncrement directement sur le rendu. Vous voulez donner à onClick une fonction qui devrait être appelée lorsque l'événement se produit à la place, par exemple () => this.handleIncrement ()


Mais pourquoi cela fonctionne-t-il pour moi un événement avec une fonction sans flèche?


Ce n'est pas le cas. Vous appelez la fonction avec le () directement sur le rendu qui vous donnera le bon this , mais ce n'est pas ce que vous voulez faire.


Je suis désolé, mais je parle de cela () dans console.log (this.state).


Veuillez relire mes commentaires précédents. Vous invoquez this.handleIncrement directement sur le rendu en écrivant this.handleIncrement() . Ce n'est pas ce que tu veux faire.


4 Réponses :


1
votes

Toute fonction appelée directement à partir de la méthode de rendu obtiendra l'objet conteneur comme this Mais lorsque nous attribuons une fonction à l'événement onClick , nous ne voulons pas appeler cette fonction immédiatement ... donc nous l'attribuons comme ceci

<button onClick={this.handleIncrement}>

(seulement le nom de la fonction sans () à la fin) ... et cela dit d'appeler la fonction lorsque le bouton est cliqué.

Mais lorsque vous cliquez sur le bouton, la fonction ne sera pas appelé depuis la méthode render donc la référence this sera modifiée et produira une erreur.

Dans votre cas, vous avez ajouté le ( ) à votre fonction this.handleIncrement en l'invoquant immédiatement ... donc cela ne pose aucun problème mais cela vous donnera des résultats erronés dans presque tous les cas car il ne sera pas appelé cliquez mais il sera appelé à chaque rendu.

Puisque votre code simple n'est rendu que sur un clic sur un bouton, il corrige probablement le problème. Ajoutez un deuxième bouton et cela donnera un mauvais résultat ou l'interface utilisateur se bloquera.

La bonne façon est de supprimer le () après this.handleIncreament et lier la fonction à l'intérieur du constructeur ... this.handleIncreament = this.handleIncreament.bind (this)


0 commentaires

0
votes

Comme Afzal Hossain le dit, vous appelez this.handleIncrement () lorsque le l'élément rend plutôt que lorsque le bouton est cliqué.

Vous devez fournir le descripteur de fonction lui-même à onClick , et bind () au bon contexte lorsqu'il est construit, de sorte que ce accède toujours l'instance de Counter dans handleIncrement().

Voici une implémentation fonctionnelle des suggestions faites dans sa réponse:

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<main/>
const { Component } = React;

class Counter extends Component {
  state = { count: 0 };
  handleIncrement = this.handleIncrement.bind(this);

  handleIncrement () {
    const { count } = this.state;
    this.setState({ count: count + 1 });
  }

  render () {
    return <label>
      <div>Count {this.state.count}</div>
      <button onClick={this.handleIncrement}>Increment</button>
    </label>;
  }
}

ReactDOM.render(<Counter/>, document.querySelector('main'));


0 commentaires

0
votes

Sans la méthode bind (), vous pouvez utiliser directement la fonction de flèche dans handleincrement. vérifiez le code ci-dessous

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<main/>
const { Component } = React;

class Counter extends Component {
  state = { count: 0 };
  

  handleIncrement=()=> {
    const { count } = this.state;
    this.setState({ count: count + 1 });
  }

  render () {
    return <label>
      <div>Count {this.state.count}</div>
      <button onClick={this.handleIncrement}>Increment</button>
    </label>;
  }
}

ReactDOM.render(<Counter/>, document.querySelector('main'));


1 commentaires

Dans la mesure du possible, faites un effort pour fournir des explications supplémentaires au lieu de simplement du code. De telles réponses ont tendance à être plus utiles car elles aident les membres de la communauté et en particulier les nouveaux développeurs à mieux comprendre le raisonnement de la solution, et peuvent aider à éviter d'avoir à répondre à des questions de suivi.



1
votes

Le fait est que lorsque votre gestionnaire d'événements a besoin d'accéder à ceci à partir d'une portée locale, et que vous appelez la méthode comme ceci; this.handleClick () , vous indiquez à JavaScript d'implémenter la tâche de la méthode IMMÉDIATEMENT qu'elle y arrive (dans votre cas, immédiatement elle est rendue), ce qui, par convention, ne nécessite pas de liaison à ceci .

Mais quand vous 'appelez' (je le mets entre guillemets car le mot juste devrait être REFER) une méthode comme celle-ci; this.handleClick , vous faites en fait référence à la méthode (ce qui signifie qu'elle ne doit être invoquée que lorsque l'utilisateur fait quelque chose), sans l'invoquer immédiatement. Cela nécessite soit la liaison this.handleClick = this.handleClick.bind (this); soit l'utilisation de la fonction de flèche pour votre méthode handleClick = () => {}; . Il est principalement utilisé pour les fonctionnalités onClick .

Vous n'obtenez pas cette erreur dans votre code car vous avez inclus les parenthèses - this.handleIncrement () . Si vous supprimez les parenthèses et toujours consoleLog this.state dans votre handleIncrement , vous obtiendrez certainement une erreur undefined . Mais si votre handleIncrement enregistre uniquement quelque chose en dehors d'un état, vous n'obtiendrez pas l'erreur.

Si vous comprenez mon explication de base, veuillez accepter la réponse.


0 commentaires