Reaktion: jsx in einer Variablen vs. einer Funktion vs. einer separaten Komponente

Lesezeit: 8 Minuten

Benutzeravatar von gaurav5430
gaurav5430

Für das Rendern kleinerer Komponenten/jsx innerhalb einer größeren Komponente gibt es mehrere Ansätze, denen man folgen kann. Betrachten Sie zum Beispiel Folgendes:

Methode 1:

function BigComponent(props) {
  const renderSmallComponent1 = () => <div>{props.a}</div>;
  const renderSmallComponent2 = () => <div>{props.b}</div>;

  return (
    <div>
      {renderSmallComponent1()}
      {renderSmallComponent2()}
    </div>
  )
}

Methode 2:

function BigComponent(props) {
  const smallComponent1 = <div>{props.a}</div>;
  const smallComponent2 = <div>{props.b}</div>;

  return (
    <div>
      {smallComponent1}
      {smallComponent2}
    </div>
  )
}

Methode 3:

function SmallComponent1({ a }) {
  return <div>{a}</div>;
}

function SmallComponent2({ b }) {
  return <div>{b}</div>;
}

function BigComponent(props) {
  return (
    <div>
      <SmallComponent1 a={props.a} />
      <SmallComponent2 b={props.b} />
    </div>
  )
}

Ich versuche nur, den Unterschied zwischen diesen 3 in Bezug auf zu verstehen

  • Entwicklererfahrung,
  • wie das Framework sie behandelt,
  • Gibt es Leistungsoptimierungen,
  • Gibt es bei all diesen Unterschieden im Laufzeitverhalten?
  • Ist eines der beiden besser in bestimmten Szenarien zu verwenden?

Das sind die Dinge, die ich verstehe:

  • in Methode 3 alle SmallComponent sind React-Komponenten, die in einer anderen Komponente gerendert werden, sodass sie einen Komponentenlebenszyklus haben, während sie in Methode 1 und 2 einfache JSX-Dateien sind, die keinen Lebenszyklus haben, sodass sie nicht als React-Komponenten gemountet / unmountet würden
  • In Methode 2 würden wir JSX eifrig auswerten, da es direkt eine Variable ist, während es in Methode 1 nur ausgewertet würde, wenn die Funktion beim Rendern aufgerufen wird. Falls wir also ein bedingtes Rendering haben, ist die eifrige Auswertung möglicherweise nur verschwenderisch.

Noch ein paar hilfreiche Artikel:

AKTUALISIEREN: Es scheint, dass Beobachtung 1 falsch ist, da alle 3 immer noch als Reaktionskomponenten gerendert würden und daher einen Komponentenlebenszyklus hätten. Reagieren würde sie also mounten/unmounten.

AKTUALISIERUNG 2: Nein, Beobachtung 1 ist richtig, Methode 1 und 2 werden beide als reguläre jsx als Teil der BigComponent behandelt und sie werden nicht als Reaktionskomponente behandelt, die einen Lebenszyklus haben.

AKTUALISIERUNG 3: Es gibt eine andere Methode Methode 4:

function BigComponent(props) {
  const SmallComponent1 = () => {
  return <div>{props.a}</div>;
  }
  const SmallComponent2 = () => {
  return <div>{props.b}</div>;
  }

  return (
    <div>
      <SmallComponent1 />
      <SmallComponent2 />
    </div>
  )
}

Dies ähnelt Methode 3, aber Methode 3 und Methode 4 unterscheiden sich geringfügig in der Ausführung beim Debuggen durch Entwicklungstools.

  • Sie scheinen die Fälle recht gut zu verstehen. Ich bin mir nicht sicher, auf welchen Aspekt Sie näher eingehen möchten?

    – hacken

    21. April 2021 um 1:49 Uhr

  • Fragen wie: Gibt es ein Szenario, in dem eine dieser Methoden anders oder gar nicht funktionieren würde? Können sie sich immer gegenseitig ersetzen?

    – gaurav5430

    21. April 2021 um 2:46 Uhr

  • Hmm, für mich klingt das immer noch nach einer sehr offenen Frage. Ich weiß nicht wirklich, wo ich anfangen soll, weil ich alle möglichen Beispiele konstruieren kann, um unterschiedliche Verhaltensweisen zu veranschaulichen.

    – hacken

    21. April 2021 um 3:48 Uhr

  • @hackape Ich denke, verschiedene Beispiele wären immer noch hilfreich und könnten die wichtigsten Teile der Frage beantworten, bei der es im Wesentlichen um die Unterschiede zwischen diesen drei Ansätzen geht

    – gaurav5430

    21. April 2021 um 3:51 Uhr

  • Anstatt spezielle Anwendungsfälle zu untersuchen, wäre es meiner Meinung nach der bessere Ansatz, die interne Arbeit von React tatsächlich zu lernen. Sobald Sie die „Physik“ gelernt haben, wissen Sie, wie man die gesamte „Technik“ macht.

    – hacken

    21. April 2021 um 3:51 Uhr

Benutzeravatar von Firoj Siddiki
Firoj Siddiki

Methode 2:

function BigComponent(props) {
  const smallComponent1 = <div>{props.a}</div>;
  const smallComponent2 = <div>{props.b}</div>;

  return (
    <div>
      {smallComponent1}
      {smallComponent2}
    </div>
  )
}
  • Wenn Sie eine große Benutzeroberfläche in eine separate kleinere Benutzeroberfläche umwandeln möchten, bietet Ihnen diese Methode die beste Leistung, weil
    • Es ist immer noch nur eine große UI-Komponente.
    • reagieren müssen nur Variablenreferenzen lösen.
    • Beim erneuten Rendern werden BigComponent, SmallComponent1 und SmallComponent2 zusammen als einzelne Einheit gerendert.
    • smallComponent1 und smallComponent2 können keine eigenen Zustände, Lebenszyklen und Hooks haben.
    • smallComponent1 und 2 sein müssen neu initialisiert Jedes Mal, wenn der Status von Bigcomponent geändert wird. Es ist also eine gute Praxis, sie damit zu umwickeln useMemo() wenn das Ergebnis dieser kleinen Komponenten aus einer teuren Berechnung stammt.

Methode 3:

function SmallComponent1({ a }) {
  return <div>{a}</div>;
}

function SmallComponent2({ b }) {
  return <div>{b}</div>;
}

function BigComponent(props) {
  return (
    <div>
      <SmallComponent1 a={props.a} />
      <SmallComponent2 b={props.b} />
    </div>
  )
}
  • React muss sowohl die Referenz auflösen als auch die Funktion nach dem Auflösen der Referenz ausführen.

  • Es ist eine Zusammensetzung der eigentlichen untergeordneten Komponenten von React zu einer großen Komponente.

  • Untergeordnete Komponenten dürfen ihre eigenen haben hooks.

  • Untergeordnete Komponenten sind nicht neu initialisiert werden aber neu gerendert, wenn der Status von BigComponent geändert wird.

  • Es besteht die Möglichkeit, dass SmallComponent1 und SmallComponent2 beim einmaligen Rendern von BigComponents mehrmals neu gerendert werden, wenn kleine Komponenten ihren eigenen Zustand basierend auf der Änderung von Requisiten in den Eltern aktualisieren.

  • Wenn jede SmallComponents mehrere Requisiten verwenden soll, deren Zustand BigComponents ist, bietet das Halten von SmallComponents außerhalb von BigComponent eine gute Entwicklererfahrung.

  • Ich hoffe, Methode 1 und Methode 4 können auch anhand dieser obigen Punkte verstanden werden.

  • Hinweis: In Variablen gespeicherte untergeordnete Komponenten und untergeordnete Komponenten als Funktion werden schwieriger, wenn Ihre Anwendungslogik das ref- oder DOM-Element verwendet, um den Fokus oder Ankerpunkt des Renderings aufrechtzuerhalten.

Benutzeravatar von t0mgerman
t0mdeutsch

Haben Sie sich das kompilierte JS in einem React-Projekt angesehen?

JSX-Tags werden im Wesentlichen in umgewandelt React.createElement Aussagen. Du kannst Lesen Sie die Dokumente hier. Im Wesentlichen lautet die Syntax:

React.createElement(FunctionOrClassComponent, { props }, ...children)

In allen drei Ihrer Beispiele würde dies stattfinden. In allen drei Beispielen sind die kleineren Komponenten eher Funktionskomponenten als Klassenkomponenten. Das heißt, sie haben nicht die React-Lebenszyklusmethoden einer Klassenkomponente, aber sie kann Verwenden Sie gleichwertige React-Hooks – wenn Sie möchten.

Bearbeitet: Die Auswertung (Instanziierung und Rendering) hängt von Ihrer Renderlogik ab. Wenn Sie bedingte Rendering-Anweisungen haben oder Ihre Funktionen basierend auf bestimmten Bedingungen null (oder weniger Inhalt) zurückgeben, leisten Sie offensichtlich weniger Arbeit. Und wie Sie in den Kommentaren unten zu Recht darauf hingewiesen haben, wenn Sie ein JSX.Element einer Variablen zuweisen, die inline und nicht als Ergebnis einer Funktion ausgewertet wird, geschieht dies sofort.

Für mich sind alle drei gültige Ansätze. Um Ihre Fragen zu beantworten:

  • Entwicklererfahrung,
    • Für kleine Komponenten mit minimalem Status sind funktionale Komponenten als Variablen oder Lambdas bequem zu schreiben und einfach zu lesen/parsen, wenn Code zu einem späteren Zeitpunkt erneut aufgerufen wird. Wenn eine Komponente komplexer wird, müssen Sie möglicherweise überdenken, wie sie geschrieben ist, und möglicherweise Klassenkomponenten verwenden.
  • wie das Framework sie behandelt,
    • Meines Wissens behandelt das Framework alle drei Ihrer Beispiele in Bezug auf die Kompilierung gleich. Ich bin mir bei der Rendering-Optimierung nicht sicher.
  • Gibt es Leistungsoptimierungen,
    • Ihre Beispiele zeigen nichts Rechenintensives, sodass die Optionen zur Leistungsoptimierung nicht so offensichtlich sind
  • Gibt es bei all diesen Unterschieden im Laufzeitverhalten?
    • Sie werden alle in React-Elemente übersetzt, auf Requisitenänderungen überwacht und neu gerendert, wenn Eltern neu rendern (wenn Dinge wie React.memo nicht verwendet werden) – es kann Unterschiede zu klassenbasierten Elementen geben, aber ich würde das vermuten Die Laufzeitunterschiede zwischen Ihren drei Beispielen sind minimal
  • Ist eines der beiden besser in bestimmten Szenarien zu verwenden?
    • Die Unterschiede zwischen allen dreien sind eher eine Frage der Standards oder der Etikette als des funktionellen Ergebnisses. Als Entwickler wäre ich in der Lage, alle drei zu lesen und zu verstehen, aber wenn ich im Team arbeite, würde ich mir einen Standardansatz wünschen.

  • In Bezug auf die eifrige Auswertung: Methode 1 würde Dinge nur auswerten, wenn die Funktion innerhalb von render/return aufgerufen wird, aber Methode 2 würde Dinge sogar vorher auswerten, da es sich um eine Variable handelt

    – gaurav5430

    21. April 2021 um 3:11 Uhr

  • In Bezug auf die Verwendung von Hooks: In Methode 1 und 2 denke ich, selbst wenn wir Hooks verwenden könnten, würden sie dem Elternteil gehören und nicht diesen kleinen Komponenten.

    – gaurav5430

    21. April 2021 um 3:16 Uhr

  • Entschuldigung, es ist spät hier – ich habe das, was Sie über die Bewertung gesagt haben, mit Eifer Loading (im Gegensatz zu Lazy Loading) verwechselt. Sie haben Recht, Methode 2 würde Dinge inline auswerten, da dies keine Funktionen, sondern JSX-Elementdeklarationen (als Variablen) sind. Wenn Sie für Methode 1 und 3 Hooks in den kleinen Komponenten verwendet und die Hook-Ausgänge deklariert und Block-Scope-Variablen zugewiesen haben (mit let oder const), würden sie zu den kleinen Komponenten gehören … sie würden nur bis zur übergeordneten Komponente hochziehen wenn du var verwendet hast.

    – t0mdeutsch

    21. April 2021 um 3:22 Uhr

  • Entschuldigung, da ist auch ein Fehler passiert … Ich wollte sagen, dass sie nur zur übergeordneten Komponente gehören würden, wenn Sie sie dort deklarieren würden.

    – t0mdeutsch

    21. April 2021 um 3:32 Uhr

1441680cookie-checkReaktion: jsx in einer Variablen vs. einer Funktion vs. einer separaten Komponente

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy