Meilleure façon de passer des paramètres dans le gestionnaire onClick

10

Ceci est mon composant J'utilise la fonction de flèche en ligne pour changer l'itinéraire onClickde div mais je sais que ce n'est pas un bon moyen en termes de performances

1. Fonction de flèche en ligne

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={() => this.changeRoute("page1")}>1</div>
      <div onClick={() => this.changeRoute("page2")}>2</div>
    </>
  )
}

2. Si j'utilise la liaison constructeur alors comment puis-je passer des accessoires?

constructor() {
  super(props)
  this.changeRoute = this.changeRoute.bind(this)
}
changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute}>1</div>
      <div onClick={this.changeRoute}>2</div>
    </>
  )
}

3. Si je supprime la fonction flèche, la fonction appelée sur le rendu lui-même

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute("page1")}>1</div>
      <div onClick={this.changeRoute("page2")}>2</div>
    </>
  )
}

4. Si j'utilise la reliure en ligne, ce n'est pas le meilleur avec les performances

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute.bind(this, "page1")}>1</div>
      <div onClick={this.changeRoute.bind(this, "page2")}>2</div>
    </>
  )
}

Alors, comment puis-je procéder avec la meilleure façon de passer les paramètres?

Chevalier noir
la source
Il est probablement intéressant de noter que la raison pour laquelle l'utilisation des fonctions de flèche en ligne ici "n'est pas [un] bon moyen en termes de performances" n'est pas parce que les fonctions de flèche seraient en quelque sorte intrinsèquement lentes à s'exécuter (elles ne le sont pas, et en tout cas le le coût d'un appel de fonction est totalement négligeable pour quelque chose d'aussi rarement exécuté qu'un gestionnaire de clics) mais parce que React créera de nouvelles instances des fonctions à chaque fois que le composant sera rendu. La liaison en ligne a exactement le même problème. Et c'est généralement bien de toute façon, à moins que le composant ne soit rendu de nouveau très fréquemment.
Ilmari Karonen le
2
@IlmariKaronen Dans la plupart des cas, les composants sont rendus fréquemment parce que les composants ont un champ de saisie et la saisie et la définition de la valeur e.target.value résultent en un rendu fréquent.
Dark Knight

Réponses:

6

Vous pouvez utiliser la fonction flèche pour définir votre changeRoutegestionnaire.

C'est ce qu'on appelle Class field syntax. Plus d'informations ici dans les documents officiels de React.

constructor() {
  super(props)
}

const changeRoute = (parameter) => (event) => {
    // business logic for route change.
}

Ensuite, vous pouvez utiliser cette fonction directement comme ceci:

render() {
  return (
    <>
      <div onClick={changeRoute(params1)}>1</div>
      <div onClick={changeRoute(params2)}>2</div>
    </>
  )
}

Vous n'avez pas à vous soucier de la reliure. Les fonctions fléchées héritent de celles de leurs parents this.

Utsav Patel
la source
@DarkKnight Votre dernier commentaire était executing on the go. Ma réponse est en réponse à cela. J'essaie de vous dire que votre gestionnaire de clics ne le sera pas execute on the gosi vous définissez le gestionnaire comme je l'ai publié.
Utsav Patel
Veuillez vérifier ceci
Dark Knight
@DarkKnight Veuillez lire ce reactjs.org/docs/handling-events.html La syntaxe des champs de classe est l'une des méthodes recommandées par les documents officiels de react.
Utsav Patel
ok merci monsieur
Dark Knight
3

Vous pouvez ajouter des données à votre div:

<div data-id={1} onClick={this.changeRoute}>1</div>

Ensuite, vous pouvez récupérer ces données dans votre gestionnaire onClick:

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}
HermitCrab
la source
Ha ha ha ... C'est possible. Mais la réaction elle-même n'a pas de solution?
Dark Knight
1

# 1 est très bien.

# 2 est également «bien», mais vous devez passer des accessoires, alors la fonction de rendu ressemblera exactement à # 1 . Vous appellerez la bindfonction 'd, car vous l'avez remplacée dans le constructeur.

# 3 est tout simplement faux, car la fonction est appelée pendant le rendu.

Et en ce qui concerne le # 4, de React Docs

Nous recommandons généralement la liaison dans le constructeur ou l'utilisation de la syntaxe des champs de classe, pour éviter ce type de problème de performances.

Cela entraîne une baisse des performances lorsque votre fonction est utilisée dans ses composants enfants et entraînera le rendu des composants enfants (ce n'est pas dans votre cas). Vous ne devriez donc pas faire # 4 .

Ben B
la source
1

La meilleure façon actuellement consiste à encapsuler votre gestionnaire d'événements dans le useCallbackcrochet car cela empêchera la création de votre fonction de gestionnaire à chaque appel de rendu.

import React, { useCallback } from 'react'

const MyComponent = ({ changeRoute }) => {
  const eventHandler = useCallback(() => {
    changeRoute('page1')
  }, [changeRoute])

  return (
    <div onClick={eventHandler}>1</div>
  )
}

Pour plus d'informations, vérifiez - useCallback docs

Aleh Atsman
la source
L'OP semble utiliser un composant de classe, où vous ne pouvez pas utiliser de hooks.
TJ Crowder
J'espère que ma réponse l'aidera à mieux comprendre
Aleh Atsman