Der beste Weg, um Parameter im onClick-Handler zu übergeben

11

Dies ist meine Komponente. Ich verwende die Inline-Pfeilfunktion, um die Route onClickvon div zu ändern, aber ich weiß, dass dies in Bezug auf die Leistung kein guter Weg ist

1. Inline-Pfeilfunktion

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

2. Wenn ich Konstruktorbindung verwende, wie kann ich dann Requisiten übergeben?

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. Wenn ich die Pfeilfunktion entferne, wird die Funktion beim Rendern selbst aufgerufen

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

4. Wenn ich Inline-Bindung verwende, ist dies auch bei der Leistung nicht am besten

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

Wie kann ich dann am besten mit der Übergabe von Parametern fortfahren?

Dunkler Ritter
quelle
Es ist wahrscheinlich erwähnenswert, dass der Grund, warum die Verwendung von Inline-Pfeilfunktionen hier "in Bezug auf die Leistung nicht [ein] guter Weg ist", nicht darin liegt, dass Pfeilfunktionen an sich nur langsam ausgeführt werden (sie sind es nicht, und auf jeden Fall die Die Kosten eines Funktionsaufrufs sind für etwas, das so selten ausgeführt wird wie ein Klick-Handler, völlig vernachlässigbar. Da React jedoch bei jedem erneuten Rendern der Komponente neue Instanzen der Funktionen erstellt. Inline-Bindung hat genau das gleiche Problem. Und normalerweise ist es sowieso in Ordnung, es sei denn, die Komponente wird sehr häufig neu gerendert .
Ilmari Karonen
2
@IlmariKaronen In den meisten Fällen wird die Komponente häufig neu gerendert, da die Komponenten über ein Eingabefeld verfügen. Wenn Sie den Status e.target.value eingeben und festlegen, wird häufig gerendert.
Dark Knight

Antworten:

6

Mit der Pfeilfunktion können Sie Ihren changeRouteHandler definieren .

Dies ist bekannt als Class field syntax. Mehr dazu hier in offiziellen Reaktionsdokumenten.

constructor() {
  super(props)
}

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

Dann können Sie diese Funktion direkt wie folgt nutzen:

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

Sie müssen sich nicht um die Bindung kümmern. Pfeilfunktionen erben die ihrer Eltern this.

Utsav Patel
quelle
@ DarkKnight Dein letzter Kommentar war executing on the go. Meine Antwort ist eine Antwort darauf. Ich versuche Ihnen zu sagen, dass Ihr Click-Handler dies nicht tut, execute on the gowenn Sie den Handler so definieren, wie ich ihn gepostet habe.
Utsav Patel
Bitte überprüfen Sie dies
Dark Knight
@DarkKnight Bitte lesen Sie diese reactjs.org/docs/handling-events.html Die Syntax von Klassenfeldern ist eine der empfohlenen Methoden in offiziellen React- Dokumenten.
Utsav Patel
ok danke sir
Dark Knight
3

Sie können Ihrem div Daten hinzufügen:

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

Anschließend können Sie diese Daten in Ihrem onClick-Handler abrufen:

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}
HermitCrab
quelle
Genialer Ansatz!
Max
Ha ha ha ... Kann getan werden. Aber die Reaktion selbst hat keine Arbeit?
Dark Knight
1

# 1 ist in Ordnung.

# 2 ist auch 'in Ordnung', aber Sie müssen Requisiten übergeben, dann sieht die Renderfunktion genau wie # 1 aus . Sie rufen die bindFunktion 'd' auf, weil Sie sie im Konstruktor ersetzt haben.

# 3 ist einfach falsch, da die Funktion beim Rendern aufgerufen wird.

Und in Bezug auf # 4 aus React Docs

Wir empfehlen im Allgemeinen, im Konstruktor zu binden oder die Syntax der Klassenfelder zu verwenden, um diese Art von Leistungsproblemen zu vermeiden.

Dies führt zu einer Leistungsminderung, wenn Ihre Funktion in ihren untergeordneten Komponenten verwendet wird, und führt dazu, dass die untergeordneten Komponenten erneut gerendert werden (in Ihrem Fall nicht). Du solltest also nicht # 4 machen .

Ben B.
quelle
1

Der derzeit beste Weg ist, Ihren Event-Handler in einen useCallbackHook zu verpacken, da dadurch verhindert wird, dass Ihre Handler-Funktion bei jedem Aufruf des Renderings erstellt wird.

import React, { useCallback } from 'react'

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

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

Für weitere Informationen überprüfen Sie - verwenden Sie Callback-Dokumente

Aleh Atsman
quelle
Das OP scheint eine Klassenkomponente zu verwenden, in der Sie keine Hooks verwenden können.
TJ Crowder
Ich hoffe, meine Antwort wird ihm helfen, den besseren Weg zu verstehen
Aleh Atsman