wake-up-neo.com

Reagieren Sie funktionale zustandslose Komponente, PureComponent, Component; Was sind die Unterschiede und wann sollten wir was verwenden?

Kam zu wissen, dass ab React v15.3.0 eine neue Basisklasse namens PureComponent mit PureRenderMixin integriert ist. Ich verstehe, dass unter der Haube ein flacher Vergleich der Requisiten in shouldComponentUpdate durchgeführt wird.

Jetzt haben wir 3 Möglichkeiten, eine React-Komponente zu definieren:

  1. Funktionale zustandslose Komponente, die keine Klasse erweitert
  2. Eine Komponente, die die Klasse PureComponent erweitert
  3. Eine normale Komponente, die die Klasse Component erweitert

Vor einiger Zeit haben wir zustandslose Komponenten als reine Komponenten oder sogar als dumme Komponenten bezeichnet. Scheint, als hätte sich die gesamte Definition des Wortes "rein" in React geändert.

Obwohl ich grundlegende Unterschiede zwischen diesen drei verstehe, bin ich mir immer noch nicht sicher, wann ich was wählen soll . Was sind auch die Auswirkungen auf die Leistung und die jeweiligen Kompromisse?


Update :

Dies sind die Fragen, von denen ich eine Klärung erwarte:

  • Soll ich meine einfachen Komponenten der Einfachheit halber als funktional definieren oder die Klasse PureComponent erweitern (aus Gründen der Leistung)?
  • Ist die Leistungssteigerung, die ich erhalte, ein echter Kompromiss für die verlorene Einfachheit?
  • Würde ich jemals die normale Klasse Component erweitern müssen, wenn ich PureComponent immer verwenden kann, um die Leistung zu verbessern?
166
free-soul

Wie entscheiden Sie sich, wie wählen Sie zwischen diesen drei Optionen aus, je nach Zweck/Größe/Requisiten/Verhalten unserer Komponenten?

Das Erweitern von React.PureComponent oder von React.Component mit einer benutzerdefinierten shouldComponentUpdate-Methode hat Auswirkungen auf die Leistung. Die Verwendung zustandsloser Funktionskomponenten ist eine "architektonische" Wahl und bietet (noch) keine Leistungsvorteile.

  • Für einfache Darstellungskomponenten, die einfach wiederverwendet werden müssen, ziehen Sie zustandslose Funktionskomponenten vor. Auf diese Weise sind Sie sicher, dass sie von der eigentlichen App-Logik entkoppelt sind, dass sie einfach zu testen sind und keine unerwarteten Nebenwirkungen haben. Die Ausnahme ist, wenn Sie aus irgendeinem Grund eine Menge von ihnen haben oder wenn Sie wirklich ihre Render-Methode optimieren müssen (da Sie shouldComponentUpdate nicht für eine zustandslose Funktionskomponente definieren können). 

  • Erweitern Sie PureComponent, wenn Sie wissen, dass Ihre Ausgabe von einfachen Requisiten/Zuständen abhängt ("simple" bedeutet keine verschachtelten Datenstrukturen, da PureComponent einen flachen Vergleich durchführt) UND Sie benötigen einige Leistungsverbesserungen.

  • Erweitern Sie Component und implementieren Sie Ihr eigenes shouldComponentUpdate, wenn Sie einige Leistungssteigerungen benötigen, indem Sie eine benutzerdefinierte Vergleichslogik zwischen nächsten/aktuellen Requisiten und dem Status ausführen. Beispielsweise können Sie schnell einen tiefen Vergleich mit lodash # isEqual durchführen:

    class MyComponent extends Component {
        shouldComponentUpdate (nextProps, nextState) {
            return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
        }
    }
    

Auch das Implementieren von shouldComponentUpdate oder das Erweitern von PureComponent sind Optimierungen. Wie üblich sollten Sie dies nur dann prüfen, wenn Sie Leistungsprobleme haben ( vermeiden Sie vorzeitige Optimierungen ). Als Faustregel versuche ich immer, diese Optimierungen vorzunehmen, nachdem sich die Anwendung im Arbeitszustand befindet und die meisten Funktionen bereits implementiert sind. Es ist viel einfacher, sich auf Leistungsprobleme zu konzentrieren, wenn sie tatsächlich in die Quere kommen.

Mehr Details

Funktionslose zustandslose Komponenten:

Diese werden nur über eine Funktion definiert. Da es für eine zustandslose Komponente keinen internen Status gibt, hängt die Ausgabe (was gerendert wird) nur von den Requisiten ab, die als Eingabe für diese Funktion angegeben werden. 

Pros: 

  • Einfachste Möglichkeit, eine Komponente in React zu definieren. Wenn Sie keinen Zustand verwalten müssen, warum sollten Sie sich mit Klassen und Vererbung beschäftigen? Einer der Hauptunterschiede zwischen einer Funktion und einer Klasse besteht darin, dass Sie mit der Funktion sicher sind, dass die Ausgabe nur von der Eingabe abhängt (nicht von der Historie der vorherigen Ausführungen).

  • Idealerweise sollten Sie in Ihrer App möglichst viele zustandslose Komponenten verwenden, da dies normalerweise bedeutet, dass Sie Ihre Logik außerhalb der Ansichtsebene verschoben haben und sie in eine Art "redux" verschoben haben. Dies bedeutet, dass Sie Ihre reale Logik testen können, ohne etwas zu rendern (viel einfacher zu testen, wiederverwendbar usw.).

Nachteile: 

  • Keine Lebenszyklusmethoden. Sie haben keine Möglichkeit, componentDidMount und andere Freunde zu definieren. Normalerweise tun Sie dies in einer übergeordneten Komponente, die höher in der Hierarchie ist, sodass Sie alle untergeordneten Elemente in zustandslose Elemente konvertieren können.

  • Es gibt keine Möglichkeit, manuell zu steuern, wann ein erneutes Rendern erforderlich ist, da Sie shouldComponentUpdate nicht definieren können. Ein erneutes Rendern erfolgt jedes Mal, wenn die Komponente neue Requisiten erhält (keine Möglichkeit zum Vergleich von flachen Ebenen usw.). In Zukunft könnte React automatisch statuslose Komponenten optimieren. Derzeit können einige Bibliotheken verwendet werden. Da zustandslose Komponenten nur Funktionen sind, handelt es sich im Grunde um das klassische Problem der "Funktionserinnerung".

  • Refs werden nicht unterstützt: https://github.com/facebook/react/issues/4936

Eine Komponente, die die PureComponent-Klasse erweitert VS Eine normale Komponente, die die Component-Klasse erweitert:

React verwendet, um eine PureRenderMixin zu haben, die Sie an eine Klasse anhängen können, die mit React.createClass-Syntax definiert ist. Das Mixin würde einfach ein shouldComponentUpdate definieren, das einen flachen Vergleich zwischen den nächsten Stützen und dem nächsten Zustand durchführt, um zu überprüfen, ob sich dort etwas geändert hat. Wenn sich nichts ändert, ist keine erneute Wiedergabe erforderlich.

Wenn Sie die ES6-Syntax verwenden möchten, können Sie keine Mixins verwenden. Zur Vereinfachung hat React eine PureComponent-Klasse eingeführt, von der Sie erben können, anstatt Component zu verwenden. PureComponent implementiert shouldComponentUpdate genauso wie PureRendererMixin. Es ist meistens eine bequeme Sache, so dass Sie es nicht selbst implementieren müssen, da ein flacher Vergleich zwischen aktuellem/nächstem Status und Requisiten wahrscheinlich das häufigste Szenario ist, das Ihnen schnelle Leistungsgewinne bescheren kann.

Beispiel: 

class UserAvatar extends Component {
    render() {
       return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
    }
} 

Wie Sie sehen, hängt die Ausgabe von props.imageUrl und props.username ab. Wenn Sie in einer übergeordneten Komponente <UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" /> mit denselben Requisiten rendern, ruft React jedes Mal render auf, auch wenn die Ausgabe genau gleich wäre. Denken Sie daran, dass React dom diffing implementiert, damit das DOM nicht aktualisiert wird. Das Dom-Diffing durchzuführen, kann jedoch teuer sein, daher wäre es in diesem Szenario eine Verschwendung. 

Wenn die UserAvatar-Komponente stattdessen PureComponent erweitert, wird ein flacher Vergleich durchgeführt. Und weil Requisiten und nextProps gleich sind, wird render überhaupt nicht aufgerufen.Hinweise zur Definition von "rein" in React:.

Im Allgemeinen ist eine "reine Funktion" eine Funktion, die bei gleicher Eingabe immer das gleiche Ergebnis auswertet. Die Ausgabe (für React ist das, was von der render-Methode zurückgegeben wird) hängt nicht von der Historie/dem Status ab und hat keine Nebenwirkungen (Operationen, die die "Welt" außerhalb der Funktion verändern).

In React sind zustandslose Komponenten gemäß der obigen Definition nicht unbedingt reine Komponenten, wenn Sie "stateless" eine Komponente aufrufen, die niemals this.setState aufruft und keine this.state verwendet.

Tatsächlich können Sie in einem PureComponent während der Lebenszyklusmethoden noch Nebenwirkungen haben. Sie können zum Beispiel eine Ajax-Anforderung in componentDidMount senden oder eine DOM-Berechnung durchführen, um die Höhe eines Divs in render dynamisch anzupassen.

Die Definition von "dummen Komponenten" hat eine "praktischere" Bedeutung (zumindest in meinem Verständnis): Eine dumme Komponente "wird" über Requisiten von einer übergeordneten Komponente informiert und weiß nicht, wie sie vorgeht, sondern verwendet Requisiten stattdessen Rückrufe.

Beispiel eines "intelligenten" AvatarComponent

class AvatarComponent extends Component { expandAvatar () { this.setState({ loading: true }); sendAjaxRequest(...).then(() => { this.setState({ loading: false }); }); } render () { <div onClick={this.expandAvatar}> <img src={this.props.username} /> </div> } }

class AvatarComponent extends Component { render () { <div onClick={this.props.onExpandAvatar}> {this.props.loading && <div className="spinner" />} <img src={this.props.username} /> </div> } }

In the end I would say that "dumb", "stateless" and "pure" are quite different concepts that can sometimes overlap, but not necessarily, depending mostly on your use case.

280
fabio.sussetto

ich bin kein Genie der Reaktion, aber aus meinem Verständnis können wir jede Komponente in folgenden Situationen verwenden

  1. Zustandslose Komponente - Dies ist die Komponente, die keinen Lebenszyklus hat. Daher sollten diese Komponenten beim Wiederholen des Wiederholungselements der übergeordneten Komponente verwendet werden, z. B. beim Rendern der Textliste, die nur die Informationen anzeigt und keine enthält auszuführende Aktionen.

  2. Reine Komponente - Dies sind die Elemente, die einen Lebenszyklus haben, und sie geben immer das gleiche Ergebnis zurück, wenn ein bestimmter Satz von Requisiten gegeben wird. Diese Komponenten können verwendet werden, wenn eine Ergebnisliste oder bestimmte Objektdaten angezeigt werden, die keine komplexen untergeordneten Elemente enthalten und zum Ausführen von Vorgängen verwendet werden, die nur sich selbst betreffen. Eine solche Liste der Benutzerkarten oder der Liste der Produktkarten (grundlegende Produktinformationen) und die einzige Aktion, die ein Benutzer ausführen kann, ist das Klicken, um die Detailseite anzuzeigen oder in den Warenkorb zu legen.

  3. Normale Komponenten oder komplexe Komponenten - Ich habe Begriff komplexe Komponente verwendet, da es sich hierbei normalerweise um Komponenten auf Seitenebene handelt und viele untergeordnete Komponenten enthalten sind. Jedes Kind kann sich auf seine eigene Art und Weise verhalten, so dass Sie nicht 100% sein können Stellen Sie sicher, dass es bei gegebenem Status dasselbe Ergebnis liefert. Wie gesagt, sollten diese normalerweise als Behälterbestandteile verwendet werden

19
abhirathore2006
  • React.Component ist die "normale" Standardkomponente. Sie deklarieren sie mit dem Schlüsselwort class und extends React.Component. Stellen Sie sich sie als eine Klasse vor, mit Lebenszyklusmethoden, Ereignishandlern und anderen Methoden. 

  • React.PureComponent ist ein React.Component, der shouldComponentUpdate() mit einer Funktion implementiert, die einen flachen Vergleich von props und state durchführt. Sie müssen forceUpdate() verwenden, wenn Sie wissen, dass die Komponente Requisiten oder verschachtelte Daten enthält, die sich geändert haben, und dass Sie erneut rendern möchten. Sie sind daher nicht besonders gut geeignet, wenn Sie Komponenten zum erneuten Rendern benötigen, wenn Arrays oder Objekte als Requisiten übergeben werden oder in Ihrem Status geändert werden. 

  • Funktionskomponenten sind solche, die keine Lebenszyklusfunktionen haben. Sie sind angeblich staatenlos, aber sie sind so nett und sauber, dass wir jetzt Haken haben (seit React 16.8), sodass Sie immer noch einen Zustand haben können. Ich denke, das sind nur "saubere Komponenten".

0
believesInSanta