web-dev-qa-db-fra.com

Valeur de ceci dans React gestionnaire d'événements

Pour une raison quelconque, la valeur de ceci est perdue dans le gestionnaire d'événements React. En lisant les documents, je pensais que réagir a fait quelques trucs ici pour s'assurer que cela était réglé à la bonne valeur

Ce qui suit ne fonctionne pas comme je m'y attendais

import React from 'react';

export default class Observer extends React.Component {

    handleClick() {
        console.log(this); //logs undefined
    }
    render() {
        return (
            <button onClick={this.handleClick}>Click</button>
        );
    }
}

Mais cela:

import React from 'react';

export default class Observer extends React.Component {

    handleClick() {
        console.log(this); //logs Observer class instance
    }
    render() {
        return (
            <button onClick={this.handleClick.bind(this)}>Click</button>
        );
    }
}

React et ES6 sont nouveaux pour moi, mais cela ne semble pas être le bon comportement?

21
jamie holliday

Il s'agit d'un comportement correct pour JavaScript et React si vous utilisez la nouvelle syntaxe class.

la fonction de liaison automatique ne s'applique pas aux classes ES6 dans v0.13.0.

Vous devrez donc utiliser:

 <button onClick={this.handleClick.bind(this)}>Click</button>

Ou l'une des autres astuces:

export default class Observer extends React.Component {
  constructor() {
    super();
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    /* ... */
  }
  render() {
      return <button onClick={this.handleClick}>Click</button>
  }
}
32
WiredPrairie

La réponse acceptée est bonne et je l'ai beaucoup utilisée dans ES6, mais je veux juste ajouter une autre solution "plus moderne" que nous avons avec ES7 (mentionnée dans les Notes de liaison automatique de la classe de composants React ): utilisez les fonctions fléchées comme propriétés de classe , alors vous n'avez pas besoin de lier ou d'envelopper votre gestionnaire n'importe où.

export default class Observer extends React.Component {
  handleClick = (e) => {
    /* ... */
  }
  render() {
      return <button onClick={this.handleClick}>Click</button>
  }
}

C'est la solution la plus simple et la plus propre à ce jour!

15
Aaron Beall

Comme d'autres l'ont dit, React ne lie pas automatiquement les méthodes à l'instance lors de l'utilisation des classes ES6. Cela dit, je prendrais l'habitude de toujours utiliser les fonctions fléchées dans les gestionnaires d'événements comme: onClick={e => this.handleClick()}

Au lieu de: onClick={this.handleClick.bind(this)}

Cela signifie que vous pouvez remplacer la méthode handleClick par un espion dans un test, ce que vous ne pouvez pas faire lorsque vous utilisez bind.

10
Anders Ekdahl