Wann sollten ES6-klassenbasierte React-Komponenten im Vergleich zu funktionalen ES6-React-Komponenten verwendet werden?

211

Nachdem ich einige Zeit mit React verbracht habe, verstehe ich den Unterschied zwischen den beiden Hauptparadigmen beim Erstellen von Komponenten.

Meine Frage ist, wann ich welche verwenden soll und warum? Was sind die Vorteile / Kompromisse von einem zum anderen?


ES6-Klassen:

import React, { Component } from 'react';

export class MyComponent extends Component {
  render() {
    return (
      <div></div>
    );
  }
}

Funktionell:

const MyComponent = (props) => {
    return (
      <div></div>
    );
}

Ich denke immer dann, wenn es keinen Zustand gibt, der von dieser Komponente manipuliert werden kann, aber ist es das?

Ich vermute, wenn ich Lebenszyklusmethoden verwende, ist es möglicherweise am besten, eine klassenbasierte Komponente zu verwenden.

omarjmh
quelle
7
Anscheinend kennen Sie die Antwort bereits.
Felix Kling
2
Wenn Sie nur eine Komponente mit Rendermethode haben, können Sie diese in eine funktionale Form umwandeln. Wenn Sie mehr als eine zustandslose Renderfunktion benötigen, verwenden Sie Klassen
just-boris
2
Um noch prägnanter zu sein, versuchen Sie const MyComponent = (props) => <div>...</div>
Folgendes
1
Ich benutze nie funktionale, wenn es vermieden werden kann. Weil ich am Ende unweigerlich auf Klassenbasis umgestalten muss. Und müssen danach oft wieder funktionsfähig gemacht werden.
Keithjgrant
Im Jahr 2020 besteht der richtige Ansatz darin, wo immer möglich Funktionskomponenten zu verwenden, da diese Haken unterstützen und Haken (in Bezug auf Leistung und Architektur) besser sind als Alternativen.
polkovnikov.ph

Antworten:

161

Sie haben die richtige Idee. Gehen Sie mit funktional, wenn Ihre Komponente nicht viel mehr tut, als einige Requisiten aufzunehmen und zu rendern. Sie können sich diese als reine Funktionen vorstellen, da sie bei gleichen Requisiten immer gleich gerendert werden und sich gleich verhalten. Außerdem interessieren sie sich nicht für Lebenszyklusmethoden oder haben ihren eigenen internen Status.

Da sie leicht sind, ist das Schreiben dieser einfachen Komponenten als Funktionskomponenten ziemlich Standard.

Wenn Ihre Komponenten mehr Funktionen benötigen, z. B. den Status beibehalten, verwenden Sie stattdessen Klassen.

Weitere Informationen: https://facebook.github.io/react/docs/reusable-components.html#es6-classes


EDIT : Vieles davon stimmte bis zur Einführung von React Hooks.

  • componentDidUpdatekann repliziert werden mit useEffect(fn), wo fnist die Funktion, die beim erneuten Rendern ausgeführt werden soll.

  • componentDidMountMethoden können repliziert werden mit useEffect(fn, []), wobei fndie Funktion beim erneuten Rendern ausgeführt werden soll und []ein Array von Objekten ist, für die die Komponente genau dann erneut rendern wird, wenn mindestens eines den Wert seit dem vorherigen Rendern geändert hat. Da es keine gibt, useEffect()wird beim ersten Mount einmal ausgeführt.

  • statekann repliziert werden mit useState(), dessen Rückgabewert auf eine Referenz des Zustands und eine Funktion, die den Zustand festlegen kann (dh const [state, setState] = useState(initState)), zerstört werden kann. Ein Beispiel könnte dies klarer erklären:

const Counter = () => {
  const [count, setCount] = useState(0)

  const increment = () => { 
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  )
}

default export Counter

In Bezug auf die Empfehlung, wann Klasse über Funktionskomponenten verwendet werden soll, empfiehlt Facebook offiziell , wo immer möglich Funktionskomponenten zu verwenden . Abgesehen davon habe ich eine Reihe von Leuten gehört, die darüber diskutierten, aus Leistungsgründen keine funktionalen Komponenten zu verwenden, insbesondere aus diesem Grund

"Ereignisbehandlungsfunktionen werden pro Render in Funktionskomponenten neu definiert"

Bitte prüfen Sie, ob Ihre Komponenten tatsächlich mit einer solchen Geschwindigkeit oder Lautstärke gerendert werden, dass dies Anlass zur Sorge gibt.

Wenn dies der Fall ist, können Sie verhindern, dass Funktionen mithilfe von useCallbackund useMemoHooks neu definiert werden. Beachten Sie jedoch, dass dies die Leistung Ihres Codes (mikroskopisch) beeinträchtigen kann .

Aber ehrlich gesagt habe ich noch nie davon gehört, dass die Neudefinition von Funktionen ein Engpass in React-Apps ist. Vorzeitige Optimierungen sind die Wurzel allen Übels - machen Sie sich darüber Sorgen, wenn es ein Problem ist

Jeff Cousins
quelle
Was ist mit Funktionen, die nicht den Status beibehalten, sondern eng mit der Komponente verbunden sind, z. B. ein dynamisches Attribut für das Rendern bestimmen?
Dennis
Dies ist der beste Artikel über den Unterschied zwischen den beiden Arten von Komponenten in React: code.tutsplus.com/tutorials/…
Arian Acosta
5
Ab Reaktion 16.8 können Sie den Status in einer Funktionskomponente über den useStateHook verwenden.
Greg
Ab React 16.8 können Sie fast alles in funktionalen Komponenten ausführen, und alle Effekte können schließlich mit nur minimalen Auswirkungen auf die Leistung modularisiert werden.
polkovnikov.ph
1
Wo finden Sie die Informationen wo Facebook officially recommends using functional components wherever possible?
Johannchopin
40

Versuchen Sie immer, zustandslose Funktionen (Funktionskomponenten) zu verwenden, wann immer dies möglich ist. Es gibt Szenarien, in denen Sie eine reguläre React-Klasse verwenden müssen:

  • Die Komponente muss den Status beibehalten
  • Die Komponente wird zu viel neu gerendert, und Sie müssen dies über steuern shouldComponentUpdate
  • Sie benötigen eine Containerkomponente

AKTUALISIEREN

Es gibt jetzt eine React-Klasse namens "React" PureComponent, die Sie erweitern können (anstatt Component) und die eine eigene implementiert shouldComponentUpdate, die für Sie den Vergleich flacher Requisiten übernimmt. Weiterlesen

ffxsam
quelle
43
Always try to use stateless functions (functional components) whenever possible.Ich habe gelesen, dass zehn Leute das sagen. Trotzdem gab keiner von ihnen eine Erklärung dafür.
Rotareti
25
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.Weitere Informationen: facebook.github.io/react/docs/…
Diogo Cardoso
2
@rotareti Ich weiß nicht, ob Sie das Gefühl haben, Ihre Frage beantwortet zu haben, aber reine Funktionen sind viel einfacher zu verstehen, zu testen und zu warten. Bei gleichen Parametern rendern sie immer dasselbe. Komponenten, die den Status beibehalten und sich ändern, wenn Lebenszyklusereignisse auftreten, sind schwerer zu verstehen. Um nicht zu sagen, dass sie manchmal nicht benötigt werden, aber ich hoffe, es ist klar, dass sie, wenn ihre Vorteile nicht benötigt werden, nur unerwünschte Heizplatten und Overhead ohne Vorteile hinzufügen.
door_number_three
Sie möchten auch eine Komponentenklasse erstellen, wenn Sie über eigene Event-Handler-Definitionen verfügen. Auf diese Weise können Sie diese Ereignishandler an die Komponente im Konstruktor vorbinden, anstatt bei jedem Rendern eine neue Funktion zu erstellen. Beachten Sie, dass dies nicht erforderlich ist, wenn alle Ihre Event-Handler von Requisiten stammen.
Dobes Vandermeer
Beachten Sie, dass die zitierte Facebook-Empfehlung nicht mehr existiert (siehe meinen Kommentar oben).
Garrett vor
34

UPDATE März 2019

https://overreacted.io/how-are-function-components-different-from-classes/

UPDATE Februar 2019:

Mit der Einführung von React-Hooks scheinen die React-Teams zu wollen, dass wir nach Möglichkeit funktionale Komponenten verwenden (was besser der funktionalen Natur von JavaScript entspricht).

Ihre Motivation:

1.) Its hard to reuse stateful logic between components
2.) Complex components become hard to understand
3.) Classes confuse both people and machines

Eine Funktionskomponente mit Hooks kann fast alles, was eine Klassenkomponente kann, ohne die oben genannten Nachteile.

Ich empfehle sie so schnell wie möglich zu verwenden.

Ursprüngliche Antwort

Funktionskomponenten sind nicht leichter als klassenbasierte Komponenten, "sie funktionieren genau wie Klassen." - https://github.com/facebook/react/issues/5677#issuecomment-241190513

Der obige Link ist etwas veraltet, aber die Dokumentation von React 16.7.0 besagt, dass Funktions- und Klassenkomponenten:

"sind aus Reacts Sicht gleichwertig." - https://reactjs.org/docs/components-and-props.html#stateless-functions

Es gibt im Wesentlichen keinen Unterschied zwischen einer Funktionskomponente und einer Klassenkomponente, die nur die Rendermethode außer der Syntax implementiert.

In Zukunft (unter Angabe des obigen Links) "könnten wir [Reagieren] solche Optimierungen hinzufügen."

Wenn Sie versuchen, die Leistung durch Eliminieren unnötiger Renderings zu steigern, bieten beide Ansätze Unterstützung. memofür Funktionskomponenten und PureComponentfür Klassen.

- https://reactjs.org/docs/react-api.html#reactmemo

- https://reactjs.org/docs/react-api.html#reactpurecomponent

Es liegt wirklich an dir. Wenn Sie weniger Boilerplate möchten, gehen Sie funktionsfähig. Wenn Sie funktionale Programmierung lieben und keinen Unterricht mögen, gehen Sie funktional. Wenn Sie Konsistenz zwischen allen Komponenten in Ihrer Codebasis wünschen, wählen Sie Klassen. Wenn Sie es leid sind, von funktionalen zu klassenbasierten Komponenten umzugestalten, wenn Sie so etwas benötigen state, entscheiden Sie sich für Klassen.

Galupuf
quelle
1
Ich denke, dass jede Komponente React erweitert. Component macht den Code besser lesbar, insbesondere für die neuen Leute. Es ist schön, wenn Sie sehen, dass eine Komponente jedes Mal auf die gleiche Weise erstellt wird. Wie @Galupuf sagte, haben einfache Komponenten nur eine Methode namens "render ()". Es ist auch schön, alles so zu gestalten, dass React.Component erweitert wird, denn wenn Sie mit dem Binden von "this", dem Status usw. beginnen möchten, müssen Sie nicht alles umgestalten, sondern nur das hinzufügen, was Sie benötigen.
Jeffski13
10

Ab React 16.8 ist der Begriff Stateless Functional Components irreführend und sollte vermieden werden, da sie nicht mehr zustandslos sind ( React.SFC veraltet , Dan Abramov bei React.SFC veraltet ). Sie können einen Status haben, sie können Hooks haben (die als Lebenszyklusmethoden) überlappen sie sich mehr oder weniger mit Klassenkomponenten

Klassenbasierte Komponenten

Funktionskomponenten:

Warum ich Funktionskomponenten bevorzuge

  • Reagieren Sie mit dem useEffect-Hook, der eine sehr klare und präzise Möglichkeit zum Kombinieren von componentDidMount, componentDidUpdateund darstelltcomponentWillUnmount Lifecycle - Methoden
  • Mit Hooks können Sie Logik extrahieren, die problemlos von mehreren Komponenten gemeinsam genutzt und getestet werden kann
  • weniger Verwirrung über das Scoping

Reagieren Sie auf die Motivation, warum Sie Haken verwenden (dh Funktionskomponenten).

Karim
quelle