Cet article traite de l’objet this
qui est indéfini dans une méthode de classe d’un composant React.
Supposons avoir le code suivant pour une application :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import React from 'react'; class App extends React.Component { constructor (props) { super(props); this.state = { color: '#07020802', active: false }; } handleClick() { console.log('this.state: ', this.state); } render() { return ( <button onClick={this.handleClick}> Log this </button> ); } } export default App; |
Dans ce composant très simple, on accède à la méthode avec this.handleClick
. Mais lorsqu’on lance l’application, et que l’on clique sur le bouton, on se retrouve avec la méchante erreur: Uncaught TypeError: Cannot read property 'state' of undefined
.
Pourquoi ? Si l’on exécute en mode non strict, this
se réfère à l’objet window
, dans le cas du mode strict, il n’est pas défini. Comment contourner cela ? Il y a deux possibilités.
Option 1 : bind
Ce n’est pas la meilleure solution, mais on peut explicitement lié l’objet this
à la méthode où l’on veut l’utiliser avec un bind
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import React from 'react'; class App extends React.Component { constructor (props) { super(props); this.state = { color: '#07020802', active: false }; this.handleClick = this.handleClick.bind(this); } handleClick() { console.log('this.state: ', this.state); } render() { return ( <button onClick={this.handleClick}> Log this </button> ); } } export default App; |
En ajoutant cette ligne au constructeur du composant, this
se réfère au composant dans la méthode gérant le click
.
Ce n’est pas, à ce qu’il parait, terriblement performant. Imaginons avoir une dizaine de boutons sur la page. Cela signifie que l’on lie 10 instances de this
à la fonction. Cela n’aura pas un gros impact sur notre exemple simple, mais l’on peut imaginer des composants bien plus complexes, et cela pourrait avoir plus d’influence sur la performance.
Option 2 : fonctions fléchées
Les fonctions fléchées ne se soucient pas du this
. Lorsque l’on utilise des fonctions fléchées, le gestionnaire d’événement est lié à l’instance du composant, et l’on n’a pas besoin d’utiliser bind
dans le constructeur.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import React from 'react'; class App extends React.Component { constructor (props) { super(props); this.state = { color: '#07020802', active: false }; } handleClick = () => { console.log('this.state: ', this.state); } render() { return ( <button onClick={this.handleClick}> Log this </button> ); } } export default App; |
Une autre façon d’appeler le gestionnaire d’événement est d’écrire la fonction fléchée dans l’attribut onClick
du composant en appelant le gestionnaire, on peut passer l’événement comme argument :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import React from 'react'; class App extends React.Component { constructor (props) { super(props); this.state = { color: '#07020802', active: false }; } handleClick(e) { console.log('this.state: ', this.state); } render() { return ( <button onClick={e => this.handleClick(e)}> Log this </button> ); } } export default App; |
Et hop, le gestionnaire d’événement a accès à l’objet this
, qui n’est plus undefined
.