Unterschied zwischen Reaktionskomponente und Reaktionselement

74

Was ist der Unterschied zwischen Reaktionskomponente und Reaktionselement? Die Dokumentation erwähnt beide, geht aber nicht ins Detail. Einige Methoden erfordern Komponenten, andere Elemente ...

Hoffmann
quelle

Antworten:

70

Hier gibt es drei verwandte Arten von Dingen mit ihren eigenen Namen:

  • Komponenten
  • Komponenteninstanzen
  • Elemente

Dies ist etwas überraschend, da Sie, wenn Sie an andere UI-Frameworks gewöhnt sind, erwarten könnten, dass es nur zwei Arten von Dingen gibt, die ungefähr Klassen (wie Widget) und Instanzen (wie new Widget()) entsprechen. Dies ist in React nicht der Fall. Komponenteninstanzen sind nicht dasselbe wie Elemente, und es besteht auch keine Eins-zu-Eins-Beziehung zwischen ihnen. Betrachten Sie zur Veranschaulichung diesen Code:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    console.log('This is a component instance:', this);
  }

  render() {
    const another_element = <div>Hello, World!</div>;
    console.log('This is also an element:', another_element);
    return another_element;
  }
}

console.log('This is a component:', MyComponent)

const element = <MyComponent/>;

console.log('This is an element:', element);

ReactDOM.render(
  element,
  document.getElementById('root')
);

Im obigen Code:

  • MyComponent(die Klasse selbst ) ist eine Komponente
  • elementist ein Element. Es ist keine Instanz von MyComponent; Vielmehr handelt es sich lediglich um eine Beschreibung der zu erstellenden Komponenteninstanz. Es ist ein Objekt mit key, props, refund typeEigenschaften. Hier keyund refsind null, propsist ein leeres Objekt, und typeist MyComponent.
  • Eine Instanz von MyComponentwird beim elementRendern erstellt (und protokolliert sich im obigen Beispiel von ihrem Konstruktor) .
  • another_elementist auch ein Element, und hat key, ref, propsund typeEigenschaften wie elementtut - aber diesmal von dem Wert typeist die Zeichenfolge "div".

Die Designgründe, warum React diese drei unterschiedlichen Konzepte hat, werden im Blog-Beitrag React Components, Elements and Instances des React-Teams , den ich zum Lesen empfehle, ausführlich untersucht .

Schließlich ist anzumerken, dass in den offiziellen Dokumenten der Begriff "Komponente" für eine Funktion oder Klasse und "Komponenteninstanz" für eine Instanz streng verwendet wird, andere Quellen diese Terminologie jedoch nicht unbedingt einhalten. Sie sollten erwarten, dass "Komponente" (falsch) als "Komponenteninstanz" verwendet wird, wenn Sie Antworten oder Diskussionen zum Stapelüberlauf auf GitHub lesen.

Mark Amery
quelle
Zusammenfassend kann Komponente verwendet werden, um eine Instanz zu erstellen, und wenn diese Instanz gerendert wird, wird ein Element erstellt.
Revanth Kumar
1
Irgendwelche Gedanken zu React Node?
Revanth Kumar
1
Wie ist das nicht eine Eins-zu-Eins-Beziehung zwischen Komponenteninstanz und Element? Schlagen Sie vor, dass ein Element mehrere Komponenteninstanzen beschreiben kann? Oder dass mehrere Elemente dieselbe Komponenteninstanz beschreiben können? Ansonsten sind sie per Definition eins zu eins miteinander verbunden.
Andy
2
@Andy Mehrere Elemente können dieselbe Komponenteninstanz beschreiben. (Nicht gleichzeitig, sondern im Laufe der Lebensdauer dieser Instanz. Wenn Sie eine übergeordnete Komponente haben, die immer <Child/>von ihrer render()Methode zurückkehrt, wird jedes Mal, wenn sie render()aufgerufen wird, ein neues Element zurückgegeben, aber eine bereits vorhandene ChildKomponente kann wiederverwendet werden, um dies zu realisieren Element.)
Mark Amery
@Andy ... und obwohl es vielleicht weniger üblich ist, können mehrere Komponenten auch von demselben Element beschrieben werden - sogar gleichzeitig. Sie können ein Element in einer Variablen speichern, z. B., el = <SomeComponent>und dieses eine Element dann mehrmals in einen großen JSX-Ausdruck einbetten, der von einer render()Methode zurückgegeben wird (d. H. Do <div>{el}{el}{el}{el}</div>).
Mark Amery
25

Um die Antwort weiter zu erläutern, verfügt ein Reaktionselement über keine Methoden und nichts über den Prototyp. Das macht sie auch schnell.

"Ein ReactElement ist eine leichte, zustandslose, unveränderliche, virtuelle Darstellung eines DOM-Elements" - Glossar der Reaktionsbegriffe

Eine Reaktionskomponentenfunktion render()gibt einen DOM-Baum von Reaktionselementen hinter den Kulissen zurück (dies ist übrigens das virtuelle DOM). Es gibt einige komplexe Mapping- und Diff-Logik, aber im Grunde sind diese React-Elemente den DOM-Elementen zugeordnet.

Sie können ein Element auch direkt erstellen, React.createElement(arg)wobei arg ein HTML-Tag-Name oder eine React Component-Klasse sein kann.

kunl
quelle
Ich bin mir nicht sicher, ob das ReactElementder VDOM selbst ist ... aber ich bin kein großer Experte in diesem Thema, das ist nur eine Vermutung. Nach meinem Verständnis muss noch eine Reaktion Elementauf ein VDOM gerendert werden, die sich dann vom "vorherigen" VDOM unterscheidet. Ich denke user6445533, die Antwort sagt dasselbe. Recht ? Ich bin kein Experte, aber irgendwie sagt mir der gesunde Menschenverstand, dass dies nach einigem Nachdenken die einzig sinnvolle Interpretation ist ... aber meine Intuition könnte falsch sein.
Jhegedus
Diese Antwort stammt aus einer langen Zeit (2015) und die VDOM-Struktur und ihr Zugriff hätten sich geändert. Ich muss es aktualisieren, denke ich, aber ich habe seitdem nicht mehr mit React gearbeitet, also muss ich zuerst recherchieren. Wenn jemand dies moderieren oder Kommentare abgeben möchte, würde ich mich sehr freuen! :)
Kunl
22

Elemente reagieren

Ein React-Element ist nur ein einfaches altes JavaScript Objectohne eigene Methoden. Es hat im Wesentlichen vier Eigenschaften:

  • type, eine StringDarstellung eines HTML-Tags oder einer Referenz, die sich auf eine Reaktionskomponente bezieht
  • key, a String, um ein Reaktionselement eindeutig zu identifizieren
  • ref, eine Referenz für den Zugriff auf den zugrunde liegenden DOM-Knoten oder die React Component Instance)
  • props(Eigenschaften Object)

Ein Reaktionselement ist keine Instanz einer Reaktionskomponente. Es ist nur eine vereinfachte "Beschreibung", wie die typezu erstellende React Component-Instanz (oder abhängig von einem HTML-Tag) aussehen soll.

Ein Reaktionselement, das eine Reaktionskomponente beschreibt, weiß nicht, auf welchen DOM-Knoten sie schließlich gerendert wird. Diese Zuordnung wird abstrahiert und beim Rendern aufgelöst.

Reaktionselemente können untergeordnete Elemente enthalten und können daher Elementbäume bilden, die den virtuellen DOM-Baum darstellen.

Komponenten reagieren und Komponenteninstanzen reagieren

Eine benutzerdefinierte Reaktionskomponente wird entweder durch React.createClassoder durch Erweitern React.Component(ES2015) erstellt. Wenn eine Reaktionskomponente instanziiert wird, erwartet sie eine props Objectund gibt eine Instanz zurück, die als Reaktionskomponenteninstanz bezeichnet wird.

Eine React-Komponente kann den Status enthalten und hat Zugriff auf die React Lifecycle-Methoden. Es muss mindestens eine renderMethode haben, die beim Aufrufen ein Reaktionselement (-tree) zurückgibt. Bitte beachten Sie, dass Sie React Component Instances niemals selbst erstellen, sondern von React für Sie erstellen lassen.

Mark Amery
quelle
Dies und Marks Antwort sind die "GUTEN" ... sie verdeutlichen den Punkt, dass React Element NICHT VDOM ist! ! ! :) :) ... Es ist ein "Lifting" - eine Art abstrakter Syntaxbaum einer Programmiersprache. Oder eine Monade. Einfach gesagt.
Jhegedus
8

Reaktionselemente vs Reaktionskomponenten

Elemente reagieren

  • Ein Reaktionselement wird von Komponenten zurückgegeben. Es ist ein Objekt, das die DOM-Knoten, die eine Komponente darstellt, virtuell beschreibt.
  • Bei einer Funktionskomponente ist dieses Element das Objekt, das die Funktion zurückgibt.
  • Bei einer Klassenkomponente ist das Element das Objekt, das die Renderfunktion der Komponente zurückgibt. R.
  • Reaktionselemente sind nicht das, was wir im Browser sehen. Sie sind nur Objekte im Gedächtnis und wir können nichts an ihnen ändern.
  • Reaktionselemente können andere typeEigenschaften als native HTML-Elemente haben.
Wir kennen folgendes:
  • Ein Reaktionselement beschreibt, was wir auf dem Bildschirm sehen möchten.
Eine komplexere Art zu sagen ist:
  • Ein React-Element ist eine Objektdarstellung eines DOM-Knotens.

_Es ist wichtig, diese Unterscheidung hier zu treffen, da das Element nicht das ist, was wir auf dem Bildschirm sehen, sondern die Objektdarstellung das ist, was gerendert wird.

Damit kann man gut reagieren:

  • React kann diese Elemente ohne großen Aufwand erzeugen und zerstören. Die JS-Objekte sind leicht und kostengünstig.
  • React kann ein Objekt von der vorherigen Objektdarstellung unterscheiden, um zu sehen, was sich geändert hat.
  • React kann das tatsächliche DOM genau dort aktualisieren, wo die erkannten Änderungen aufgetreten sind. Dies hat einige Leistungsvorteile.
Mit dieser createElementMethode können wir eine Objektdarstellung eines DOM-Knotens (auch bekannt als React-Element) erstellen .
const element = React.createElement(
  'div',
  {id: 'login-btn'},
  'Login'
  )
Hier werden createElementdrei Argumente angeführt
  1. Der Tag-Name (z. B. div, span usw.)
  2. Alle Attribute, die das Element haben soll
  3. Der Inhalt der untergeordneten Elemente des Elements (z. B. der Text, der lautet Login)
Der createElementAufruf gibt ein Objekt zurück
{
  type: 'div',
  props: {
    children: 'Login',
    id: 'login-btn'
  }
}
Wenn dies in das DOM gerendert wird (mit ReactDOM.render), haben wir einen neuen DOM-Knoten, der so aussieht:
<div id='login-btn'>Login</div>

Huzzah!

Huzzah

Im Allgemeinen wird React von einem Komponenten-First-Ansatz aus gelehrt. Das Verständnis von Elementen-First ermöglicht jedoch einen reibungslosen Übergang zu Komponenten.

Komponenten reagieren

Eine Komponente ist eine Funktion oder eine Klasse, die optional Eingaben akzeptiert und ein React-Element zurückgibt.

  • Eine Reaktionskomponente ist eine Vorlage. Eine Blaupause. Eine globale Definition. Dies kann entweder eine Funktion oder eine Klasse sein (mit einer Renderfunktion).

  • Wenn reag eine Klasse oder eine Funktion als erstes Argument sieht, prüft es, welches Element es angesichts der entsprechenden Requisiten rendert, und setzt dies fort, bis keine createElementAufrufe mehr vorhanden sind, deren erstes Argument eine Klasse oder eine Funktion ist .

  • Wenn React ein Element mit einem Funktions- oder Klassentyp sieht, konsultiert es diese Komponente, um zu erfahren, welches Element es angesichts der entsprechenden Requisiten zurückgeben soll.

  • Am Ende dieses Prozesses verfügt React über eine vollständige Objektdarstellung des DOM-Baums. Dieser gesamte Prozess wird in React als Versöhnung bezeichnet und jedes Mal ausgelöst setStateoder ReactDOM.renderaufgerufen.

Klassenbasierte Komponenten

Die Klassensyntax ist eine der häufigsten Methoden zum Definieren einer React-Komponente. Es ist zwar ausführlicher als die funktionale Syntax, bietet jedoch mehr Kontrolle in Form von Lifecycle-Hooks.

  • Wir können viele Instanzen derselben Komponente rendern.
  • Die Instanz ist das Schlüsselwort "this", das in der klassenbasierten Komponente verwendet wird.
  • Wird nicht manuell erstellt und befindet sich irgendwo im Speicher von React.

Erstellen Sie eine Klassenkomponente

// MyComponent.js
import React, { Component } from 'react';

class MyComponent extends Component {
  render() {
    return (
      <div>This is my component.</div>
    );
  }
}

export default MyComponent;

Verwenden Sie es in jeder anderen Komponente

// MyOtherComponent.js
import React, { Component } from 'react';
import MyComponent from './MyComponent';

class MyOtherComponent extends Component {
  render() {
    return (
      <div>
        <div>This is my other component.</div>
        <MyComponent />
      </div>
    );
  }
}

export default MyOtherComponent;

Verwenden Sie Requisiten

<MyComponent myProp="This is passed as a prop." />

Auf Requisiten kann mit zugegriffen werden this.props

class MyComponent extends Component {
  render() {
    const {myProp} = this.props;
    return (
      <div>{myProp}</div>
    );
  }
}

Status verwenden

class MyComponent extends Component {
  render() {
    const {myState} = this.state || {};
    const message = `The current state is ${myState}.`;
    return (
      <div>{message}</div>
    );
  }
}

Verwenden von Lifecycle-Hooks

class MyComponent extends Component {
  // Executes after the component is rendered for the first time
  componentDidMount() {
    this.setState({myState: 'Florida'});
  }

  render() {
    const {myState} = this.state || {};
    const message = `The current state is ${myState}.`;
    return (
      <div>{message}</div>
    );
  }
}
Funktionsbasierte Komponenten
  • Habe keine Instanzen.
  • Kann mehrmals gerendert werden, aber React ordnet nicht jedem Rendern eine lokale Instanz zu.
  • React verwendet den Aufruf der Funktion, um zu bestimmen, welches DOM-Element für die Funktion gerendert werden soll.

Mit createElement

function Button ({ addFriend }) {
  return React.createElement(
    "button",
    { onClick: addFriend },
    "Add Friend"
  )
}

function User({ name, addFriend }) {
  return React.createElement(
    "div",
    null,
    React.createElement(
      "p",
      null,
      name
    ),
    React.createElement(Button, { addFriend })
  )
}

Mit was createElementkehrt zurück

function Button ({ addFriend }) {
  return {
    type: 'button',
    props: {
      onClick: addFriend,
      children: 'Add Friend'
    }
  }
}

function User ({ name, addFriend }) {
  return {
    type: 'div',
    props: {
      children: [
        {
          type: 'p',
          props: {
            children: name
          }
        },
        {
          type: Button,
          props: {
            addFriend
          }
        }
      ]
    }
  }
}

Hier haben wir eine ButtonKomponente, die eine onLoginEingabe akzeptiert und ein React-Element zurückgibt.

  • Die ButtonKomponente erhält eine onLoginMethode als Eigenschaft.
  • Um dies an unsere Objektdarstellung des DOM weiterzugeben, geben wir es als zweites Argument an createElement weiter, genau wie wir es mit dem idAttribut getan haben.
Killscreen
quelle
7

React Element- Es ist ein einfaches Objekt, das einen DOM-Knoten und seine Attribute oder Eigenschaften beschreibt, die Sie sagen können. Es ist ein unveränderliches Beschreibungsobjekt, auf das Sie keine Methoden anwenden können.

Z.B -

<button class="blue"></button>

React Component- Es ist eine Funktion oder Klasse, die eine Eingabe akzeptiert und ein React-Element zurückgibt. Es muss Verweise auf seine DOM-Knoten und auf die Instanzen der untergeordneten Komponenten beibehalten.

const SignIn = () => (
  <div>
   <p>Sign In</p>
   <button>Continue</button>
   <button color='blue'>Cancel</button>
  </div>
);
Nitin Tulswani
quelle
7

Eine Komponente ist eine Fabrik zum Erstellen von Elementen.

Ian Warburton
quelle
3

Ein Element ist ein einfaches Objekt, das beschreibt, was auf dem Bildschirm in Bezug auf die DOM-Knoten oder andere Komponenten angezeigt werden soll. Elemente können andere Elemente in ihren Requisiten enthalten. Das Erstellen eines React-Elements ist billig. Sobald ein Element erstellt wurde, wird es nie mehr mutiert. Die Objektdarstellung des React-Elements wäre wie folgt:

const element = React.createElement(
  'div',
  {id: 'login-btn'},
  'Login'
)

Das obige createElement gibt als Objekt wie folgt zurück:

{
  type: 'div',
  props: {
    children: 'Login',
    id: 'login-btn'
  }
}

Und schließlich wird es mit ReactDOM.render wie folgt in das DOM gerendert.

<div id='login-btn'>Login</div>

Während eine Komponente auf verschiedene Arten deklariert werden kann. Es kann eine Klasse mit einer render () -Methode sein. Alternativ kann es in einfachen Fällen als Funktion definiert werden. In beiden Fällen werden Requisiten als Eingabe verwendet und ein Elementbaum als Ausgabe zurückgegeben. JSX wurde am Ende als createElement transpiliert.

function Button ({ onLogin }) {
  return React.createElement(
    'div',
    {id: 'login-btn', onClick: onLogin},
    'Login'
  )
}
Vipul
quelle
0

Hier ist meine Einstellung:

Elementbeschreibt, wie das VDOM erstellt wird. Es ist im Grunde eine "eingefrorene" Version des entsprechenden Component Instance.

Wenn alles wäre, functional componentwäre keine zusätzliche Reaktion erforderlich Element. Die functional componentHierarchie könnte den VDOM-Baum direkt erzeugen.

Eine Reaktionshierarchie Component Instance( tree) ist eine "Fabrik", und diese Fabrik wird durch die Requisiten parametrisiert, die der Wurzelreaktion zugeführt werden, Component Instanceund durch den gesamten Zustand, der irgendwo im Component InstanceBaum "gespeichert" ist .

Die Reaktion Elementist also im Grunde ein "abstrakter Syntaxbaum", der in das eigentliche VDOM kompiliert wird.

Warum also nicht das VDOM direkt mit der Reaktion generieren Component Instances? Das ist hier die eigentliche Frage.

Auf den ersten Blick verstehe ich nicht, warum das nicht möglich wäre. Die Antwort lautet also höchstwahrscheinlich, dass es sich um eine Frage der Leistung handelt.

Die Reaktion Elementist eine Abstraktionsebene zwischen dem VDOM und dem Component Instance, warum diese Abstraktion benötigt wird, ist mir nicht ganz klar, höchstwahrscheinlich erlaubt sie Optimierungen. Beispielsweise wird der ElementBaum nicht vollständig gerendert, wenn eine Lebenszyklusmethode auf dem Component Instancebesagt, dass dieser Teilbaum nicht gerendert werden muss.

In diesem Fall "benötigt" die Logik, die diese Optimierung handhabt, diese zusätzliche Indirektionsebene - da die Informationen an einem Ort gespeichert werden müssen, an dem ein Teil des VDOM nicht mit dem neuen VDOM verglichen werden sollte, noch mehr, vielleicht der neue VDOM sollte überhaupt nicht berechnet werden. Die Verwendung einer zusätzlichen Indirektionsebene vereinfacht die Renderlogik und führt zu einer saubereren und wartbareren Implementierung - wie ich mir vorstellen kann.

Dieses Konzept in Haskell heißt " Heben ":

Zum Beispiel sind Monaden in Haskell perfekte Beispiele für solche Aufzüge.

Eine Monade ist eine Art Beschreibung einer Berechnung, die wie folgt als Wert gespeichert werden kann 42. In ähnlicher Weise reagieren ElementsElemente einer Beschreibung, wie das "neue" VDOM berechnet wird. Wenn jemand es berechnen will.

Dieser Vortrag beschreibt dieses Konzept einer "zusätzlichen" Indirektion mit einigen einfachen Beispielen :

Mit anderen Worten: Vorzeitige Optimierung ist die Wurzel allen Übels.

Oder: Grundsatz der Softwareentwicklung

Der Grundsatz der Softwareentwicklung (FTSE) ist ein Begriff, der von Andrew Koenig stammt, um eine Bemerkung von Butler Lampson 1 zu beschreiben, die dem verstorbenen David J. Wheeler zugeschrieben wird: 2

Wir können jedes Problem lösen, indem wir eine zusätzliche Indirektionsebene einführen.

Nach meinem Verständnis sind Reagieren Elementsein Implementierungsdetail, um die Komplexität angemessen zu handhaben und eine gewisse Optimierung (Leistung) zu ermöglichen. Ich verstehe nicht, warum man diese zusätzliche Indirektion nicht loswerden konnte - im Prinzip - reagieren würde immer noch "genauso gut" funktionieren - aber es könnte sehr langsam sein, die Implementierung und Wartung der reaktionsfähigen "Engine" selbst wäre wahrscheinlich ein Albtraum .

Bitte korrigieren Sie mich, wenn mir hier etwas fehlt.

Zitieren eines WICHTIGEN Teils der Antwort von user6445533:

type, eine Zeichenfolge, die ein HTML-Tag oder eine Referenz darstellt, die auf eine Reaktionskomponente verweist

DAS IST DER SCHLÜSSEL ^^^^

Element IST NICHT VDOM.

jhegedus
quelle
-1

A React Elementist das, was Sie als grundlegendes HTML-Element (genauer gesagt dom) betrachten würden. Es ist nur eine Möglichkeit, Elemente zu erstellen, ohne das umstrittene jsx-Format zu verwenden.

A React Componentist das, was Sie als Objekt betrachten können. Es hat seine Methoden, unterstützt React lifecyclesund ist im Allgemeinen nicht wiederverwendbar (zumindest noch keine Wiederverwendung gefunden, willkommen zu Beispielen). Es muss unbedingt eine Renderfunktion haben.

A React Classnennt man eine Klasse. Funktionalität weise React Classund React Componentsind gleich. Nur die Syntax ist die eigentliche Änderung, auf der React Componentbasiert ES6 syntax. Eine weitere wichtige Änderung ist, dass die Standardbindung von Funktionen an diese nicht mehr unterstützt wird, es sei denn, Sie verwenden Pfeilfunktionen. Mixinswerden ab sofort auch nicht mehr unterstützt ES6.

das Dunkle
quelle
-1

Elemente sind Thunks.

Mit React können Sie Benutzeroberflächen als reine Funktionen definieren, die im Anwendungsstatus definiert sind. Dies könnte implementiert werden, indem die gesamte Benutzeroberfläche bei jeder Statusänderung berechnet wird. Dies wäre jedoch teuer. Elemente sind rechnerische Beschreibungen (Thunks). Wenn sie sich nicht ändern und Sie PureComponents verwenden, wird React diesen Teilbaum nicht neu berechnen.

Michael Gummelt
quelle
Dies beantwortet die Frage nicht.
Janez Kuhar
-2

Reaktionskomponenten sind veränderlich, Elemente dagegen nicht

Sourabh
quelle