Il modo migliore per passare i parametri nel gestore onClick


11

Questo è il mio componente che sto usando la funzione freccia in linea per cambiare il percorso onClickdel div ma so che non è un buon modo in termini di prestazioni

1. Funzione freccia in linea

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

2. Se uso l'associazione del costruttore, come posso passare gli oggetti di scena?

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. Se rimuovo la funzione freccia, la funzione richiamata sul rendering stesso

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

4. Se uso l'associazione in linea, non è anche meglio con le prestazioni

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>
    </>
  )
}

Quindi come posso procedere nel modo migliore passando i parametri?


Probabilmente vale la pena notare che il motivo per cui utilizzare le funzioni freccia in linea qui "non è [un] buon modo in termini di prestazioni" non è perché le funzioni freccia sarebbero in qualche modo intrinsecamente lente da eseguire (non lo sono, e in ogni caso il il costo di una chiamata di funzione è totalmente trascurabile per qualcosa eseguito raramente come un gestore di clic) ma perché React creerà nuove istanze delle funzioni ogni volta che il componente viene renderizzato nuovamente. L'associazione in linea ha lo stesso identico problema. E di solito va bene comunque, a meno che il componente non venga ridistribuito molto frequentemente.
Ilmari Karonen,

2
@IlmariKaronen Nella maggior parte dei casi il componente esegue il rendering di frequente perché i componenti hanno un campo di input e digitando e impostando e.target.value nello stato si ottiene un rendering frequente.
Dark Knight,

Risposte:


6

È possibile utilizzare la funzione freccia per definire il changeRoutegestore.

Questo è noto come Class field syntax. Maggiori informazioni qui nei documenti ufficiali di reazione.

constructor() {
  super(props)
}

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

Quindi puoi usare questa funzione direttamente in questo modo:

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

Non devi preoccuparti del legame. Le funzioni freccia ereditano quelle dei loro genitori this.


@DarkKnight Il tuo ultimo commento è stato executing on the go. La mia risposta è in risposta a quello. Sto cercando di dirti che il gestore dei clic non lo farà execute on the gose lo definisci come ho pubblicato.
Utsav Patel,

Per favore, controlla questo
Dark Knight il

@DarkKnight Si prega di leggere il messaggio di reazione ufficiale.
Utsav Patel,

ok grazie signore
Dark Knight

3

Puoi aggiungere un dato al tuo div:

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

Quindi puoi recuperare quei dati nel tuo gestore onClick:

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}

Approccio geniale!
Max

Ah ah ah ... Può essere fatto. Ma lo stesso reagire non ha problemi?
Dark Knight,

1

# 1 va bene.

Anche il n. 2 va bene, ma è necessario passare oggetti di scena, quindi la funzione di rendering apparirà esattamente come il n . 1 . Chiamerai la bindfunzione d, perché l'hai sostituita nel costruttore.

# 3 è semplicemente sbagliato, poiché la funzione viene chiamata durante il rendering.

E per quanto riguarda il n. 4, dai documenti di reazione

In genere si consiglia l'associazione nel costruttore o l'utilizzo della sintassi dei campi di classe, per evitare questo tipo di problema di prestazioni.

Ciò causa una penalità per le prestazioni quando la funzione viene utilizzata nei suoi componenti figlio e causerà il rendering dei componenti figlio (non è nel tuo caso). Quindi non dovresti fare il 4 .


1

Il modo migliore attualmente è avvolgere il gestore eventi in modo useCallbackda impedire la creazione della funzione del gestore ogni volta che viene chiamato il rendering.

import React, { useCallback } from 'react'

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

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

Per ulteriori informazioni, controlla: usa i documenti Callback


L'OP sembrerebbe utilizzare un componente di classe, in cui non è possibile utilizzare gli hook.
TJ Crowder,

Spero che la mia risposta lo aiuti a capire il modo migliore
Aleh Atsman il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.