So vermeiden Sie Bindungs- oder Inline-Pfeilfunktionen innerhalb der Rendermethode
Lesezeit: 7 Minuten
Mayank Shukla
Wir sollten die Methodenbindung innerhalb des Renderns vermeiden, da beim erneuten Rendern die neuen Methoden erstellt werden, anstatt die alte zu verwenden, was sich auf die Leistung auswirkt.
Betrachten wir nun den Fall, in dem wir einige zusätzliche Parameter übergeben möchten, sagen wir in einer einfachen Aufgaben-App, bei einem Klick auf ein Element muss ich das Element aus dem Array löschen, dafür muss ich entweder den Elementindex oder den Aufgabennamen in jedem übergeben onClick-Methode:
Das Problem bei dieser Syntax besteht darin, dass bei jedem Rendern der Komponente ein anderer Callback erstellt wird.
Frage:
Wie kann man diese Art der Bindung innerhalb der Rendermethode vermeiden oder was sind die Alternativen dazu?
Bitte geben Sie eine Referenz oder ein Beispiel an, danke.
Shubham Khatri
Zuerst: Eine einfache Lösung besteht darin, eine Komponente für den Inhalt innerhalb einer Kartenfunktion zu erstellen und die Werte als Requisiten zu übergeben. Wenn Sie die Funktion von der untergeordneten Komponente aufrufen, können Sie den Wert an die als Requisiten übergebene Funktion übergeben.
PS Dies ist jedoch keine beste Lösung und führt immer noch dazu, dass mehrere Funktionen erstellt werden, ist aber immer noch eine Verbesserung gegenüber dem ursprünglichen Fall.
Dritter: Eine geeignetere Lösung hierfür ist jedoch das Hinzufügen von an attribute zum obersten div und erhalte den Wert von event wie
In diesem Fall werden die Attribute jedoch mithilfe der toString-Methode in Zeichenfolgen konvertiert, und daher wird ein Objekt konvertiert [Object Object] und und Array wie ["1" , "2", "3"] als "1, 2, 3"
Ja, das können wir tun, aber damit müssen wir separate Komponenten erstellen und die Eltern-Kind-Beziehung einfügen. Ich denke, das wird nicht so skalierbar sein, da wir diese Art der Bindung in großen Anwendungen früher an mehreren Stellen durchgeführt haben.
– Mayank Shukla
12. Juli 2017 um 9:38 Uhr
Ich habe auch damit zu kämpfen, und meine Schlussfolgerung ist, dass, wenn diese Neuerstellung von Funktionen Ihre Anwendung verlangsamt (was … ich denke … passieren könnte, wenn Sie einen ausreichend großen Datensatz haben, der viel neu gerendert wird ), sollten Sie diesem Ansatz für diese Komponenten folgen. Ansonsten ist es nicht wirklich ein Problem für die Leistung und kann daher getrost ignoriert werden.
– Kris Selbekk
12. Juli 2017 um 9:41 Uhr
Ja, aber das, wie Sie vermeiden können, was Sie wollen, und Skalierbarkeit sollte hier kein Problem sein
– Shubham Khatri
12. Juli 2017 um 9:42 Uhr
In Ihren ersten beiden Codeblöcken verwenden Sie beim Erstellen der Klasseneigenschaft deleteTodoaber wenn Sie darauf verweisen, verwenden Sie _deleteTodo. Ist das ein Fehler oder hat der Unterstrich hier einen besonderen Zweck?
– kojow7
12. Februar 2018 um 15:38 Uhr
@akshaykishore, Sie können in einem solchen Fall den dritten Ansatz verwenden, anstatt den Index an onClick zu übergeben
– Shubham Khatri
28. Juni 2019 um 7:42 Uhr
Wie kann man diese Art der Bindung innerhalb der Rendermethode vermeiden oder was sind die Alternativen dazu?
Wenn Sie sich für das erneute Rendern interessieren shouldComponentUpdate und PureComponent sind Ihre Freunde und helfen Ihnen bei der Optimierung des Renderings.
Sie müssen die “Child”-Komponente aus der “Parent”-Komponente extrahieren und immer dieselben Props und Implements übergeben shouldComponentUpdate oder verwenden PureComponent. Was wir wollen, ist ein Fall, wenn wir ein Kind entfernen, andere Kinder sollten nicht erneut gerendert werden.
danke für den Vorschlag, aber ich denke, die Verwendung eines eindeutigen Schlüssels wird dieses Problem lösen Was wir wollen, ist ein Fall, wenn wir ein Kind entfernen, andere Kinder sollten nicht erneut gerendert werden da ich nur ein einzelnes div mit text rendern möchte. Dieser Ansatz wird eine große Rolle spielen, wenn die Komponente groß ist und wir ein erneutes Rendern vermeiden möchten.
– Mayank Shukla
12. Juli 2017 um 10:02 Uhr
Verwenden key Eigenschaft löst dieses Problem nicht, siehe: codesandbox.io/s/xVZ7pL6E auch wenn Sie verwenden key Eigenschaft, render() von anderen <Product /> werden auch genannt. Die einzige Änderung zwischen Demo und diesem Link ist Product extends Component anstatt PureComponent.
– Dawid Karabin
12. Juli 2017 um 10:46 Uhr
Dokumentation regt zur Nutzung an Datenattribute und von innen darauf zugreifen evt.target.dataset:
_deleteTodo = (evt) => {
const elementToDelete = evt.target.dataset.el;
this.setState(prevState => ({
todos: prevState.todos.filter(el => el !== elementToDelete)
}))
}
// and from render:
todos.map(
el => <div key={el} data-el={el} onClick={this._deleteTodo}> {el} </div>
)
Ebenfalls Hinweis dass dies nur bei Leistungsproblemen sinnvoll ist:
Ist es in Ordnung, Pfeilfunktionen in Rendermethoden zu verwenden?
Im Allgemeinen ja, es ist in Ordnung, und es ist oft der einfachste Weg, Parameter an Callback-Funktionen zu übergeben.
Wenn Sie Leistungsprobleme haben, optimieren Sie auf jeden Fall!
Da Ihre Antwort jetzt aus dem Jahr 2018 stammt, können Sie heute einfach “React Hook” verwenden, um sie zu teilen.
– Isaak
13. November 2018 um 9:28 Uhr
Redest du von useCallback?
– strelets
13. November 2018 um 9:30 Uhr
grebenyuksv
Diese Antwort https://stackoverflow.com/a/45053753/2808062 ist definitiv erschöpfend, aber ich würde sagen, dass das Bekämpfen übermäßiger Re-Renderings, anstatt nur den winzigen Callback neu zu erstellen, Ihnen mehr Leistungsverbesserungen bringen würde. Das wird normalerweise durch die Implementierung einer richtigen erreicht shouldComponentUpdate in der untergeordneten Komponente.
Selbst wenn die Requisiten genau gleich sind, wird der folgende Code untergeordnete Elemente immer noch neu rendern, es sei denn, sie verhindern dies selbst shouldComponentUpdate (Sie könnten es von erben PureComponent):
Um ein erneutes Rendern zu vermeiden, muss die untergeordnete Komponente implementiert werden shouldComponentUpdate ohnehin. Jetzt ist die einzig vernünftige Implementierung das vollständige Ignorieren onClick unabhängig davon, ob es sich geändert hat: