ReactJs - Parametrisierte Event Handler

Häufig wird man Parameter bei Event Handler in ReactJs Komponenten übergeben müssen. Dazu gibt es unterschiedliche Möglichkeiten dies zu realisieren.

bind() Funktion

Wir können ein Event Handler definieren und diesen mit der JavaScript Function.prototype.bind() Funktion mit this an die Kompoenente binden.

clickFunction(e) {
    console.log('Clicked', e);
}

render() {
    <button onClick={this.clickFunction.bind(this)}></button>
}

Wenn wir nun eigene Parameter mit übergeben möchten, können wir dies einfach im bind call definieren, indem wir unseren eigenen Parameter als zweites Argument übergeben.

clickFunction(param, e) {
    console.log('Parameter', param);
    console.log('Event', e);
}

render() {
    <button onClick={this.clickFunction.bind(this, param)}></button>
}

Zu beachten ist dabei, dass unser Paramter im Event Hander in der render() Funktion als zweiter Parameter, jedoch in der clickFunction() Funktion als erster Parameter angegeben wird.

Das Problem am obigen Beispiel ist, dass bei jeden rendern der Komponente eine neue Funktion erzeugt wird. Dies ist nicht sonderlich schön für die Performance, da dadurch auch der Garbage Collector öfters aufräumen muss als nötig. Es kann dadurch auch zu unnötigen re-rendering führen, falls die Funktion über die Props übergeben wurde.

Um es zu vermeiden, dass jedes mal beim rendern eine neue Funktion erzeugt wird, können wir die Funktion im Konstruktor definieren.

class MyComponent extends React.Component {

  constructor() {
    super();
    this.clickFunction = this.clickFunction.bind(this, 'Parameter');
  }

  clickFunction(param, e) {
    console.log('Parameter', param);
    console.log('Event', e);
  }

  render() {
    <button onClick={this.clickFunction}></button>
  }
}

Nun muss die Funktion nicht mehr mit bind() am Event Handler gebunden werden. Jedoch ist uns nun hier die Möglichkeit verloren gegangen, dynamische Daten im Parameter zu übergeben.

ES6 Arrow Funktion

Jedes mal die bind() Funktion anzufügen ist auf dauer lästig. Es bietet sich daher an die Arrow Funktion zu verwenden, welches die bind() Funktion automatisch aufruft.

clickFunction(e) {  
  console.log('Event', e);
}

render() {
  <button onClick={(e) => this.clickFunction(e)}></button>
}

Wir können hier auch eigene Paramteter angeben:

handleClick(param, e) {
  console.log('Parameter', param);
  console.log('Event', e);
}

render() {
  <button onClick={(e) => this.handleClick(param, e)}></button>
}

Das Problem bei den beiden Beispielen oben ist, dass auch hier bei jedem render eine neue Funktion erzeug wird und der Garbage Collector viel zu tun bekommt.

Um dies zu vermeiden können wir die Property Initializer Syntax verwenden um die Funktion als Callback zu binden.

clickFunction = (e) => {
  console.log('Event', e);
}

render() {
  <button onClick={this.clickFunction}></button>
}

Um eigene Parameter einem Event Handler zuzuweisen während wir die Property Initializer Syntax verwenden, müssen wir Currying verwenden.

clickFunction = (param) => (e) => { 
  console.log('Event', e);
  console.log('Parameter', param);
}

render() {
  <button onClick={this.clickFunction('Parameter')}></button>
}

Jedoch ist auch hier Performance Technisch das Problem, dass bei jedem Aufruf für das Ergebnis beim Currying eine neue Instanz erzeugt wird.

Fazit

Anhand der oben gezigten Beispiele, scheint die Variante mit der Arrow Funktion zusammen mit Currying die sauberste Lösung zu sein (auch wenn diese nicht die performanteste Lösung ist) um eigene Parameter bei Event Handlern anzugeben.

Was haltest Ihr davon? Schreibt es in die Kommentare.

Diese Webseite verwendet Cookies, beim Absenden von Kommentaren. Hier finden Sie weitere Informationen zum Datenschutz Akzeptieren