Menu

React Fragment: <>...</> vs. <Fragment> mit Beispielen

Ein React Fragment fasst mehrere Elemente zu einem Rückgabewert zusammen, ohne der Seite einen Knoten hinzuzufügen. Lerne die kurze Syntax <>...</>, wann du <Fragment key> brauchst und warum Fragments in Tabellen und Listen wichtig sind.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Mit einem React Fragment gibt eine Komponente mehrere Elemente zurück, ohne sie in ein zusätzliches <div> zu packen. Schreib <> vor das erste Element und </> nach das letzte, und React setzt die Elemente direkt in das Elternelement, ohne eigenen Knoten auf der Seite.

Jedes Greeting gibt eine Überschrift und einen Absatz nebeneinander zurück. Lösche die Zeilen <> und </>, und die Vorschau zeigt stattdessen einen Build-Fehler, weil die Funktion jetzt versucht, zwei Werte zurückzugeben.

Warum eine Komponente einen Root braucht

JSX ist eine schönere Art, Funktionsaufrufe zu schreiben. <h2>Hi</h2> wird ungefähr zu jsx('h2', { children: 'Hi' }) kompiliert, ein Ausdruck. Eine return-Anweisung kann einen Wert zurückgeben, also sind zwei Geschwister-Tags ohne etwas drumherum wie return a b: Der Compiler stoppt mit „Adjacent JSX elements must be wrapped in an enclosing tag“.

Bevor es Fragments gab, war die Lösung ein umschließendes <div>. Das funktioniert, aber das div ist ein echtes Element. Es taucht im DOM auf, nimmt am CSS-Layout teil, und manche Elternelemente akzeptieren es gar nicht als Kind. Ein Fragment erfüllt die Regel mit dem einen Root und verschwindet dann.

Du kannst sehen, dass es nichts hinzufügt. Das Beispiel unten rendert dieselben zwei Einträge über ein Fragment und über ein div und zählt dann die direkten Kinder jedes Containers.

Die Konsole gibt 2 für das Fragment aus, die beiden Spans, und 1 für das div, das sie umschließt. In einem Flex- oder Grid-Container entscheidet dieser Unterschied, ob die Spans als einzelne Items angeordnet oder zu einem gebündelt werden.

Kurze Syntax und die Fragment-Komponente

Es gibt zwei Schreibweisen für ein Fragment, und beide werden zum selben kompiliert:

import { Fragment } from 'react';

// Short syntax, no import needed
<>
    <dt>React</dt>
    <dd>A library for building user interfaces</dd>
</>

// Long form
<Fragment>
    <dt>React</dt>
    <dd>A library for building user interfaces</dd>
</Fragment>

Nutze fast überall <>...</>. Zu <Fragment> greifst du in einem Fall: wenn das Fragment einen key braucht. Die kurze Syntax kann keine Attribute annehmen, also ist <key={id}> kein gültiges JSX. In älterem Code siehst du vielleicht auch <React.Fragment>; das ist dieselbe Komponente, erreicht über den Default-Import React.

Fragments mit key in Listen

Wenn du eine Liste mit map renderst, braucht jeder Eintrag einen key, damit React ihn zwischen Renders verfolgen kann (die Seite zu Listen und Keys erklärt, warum). Wenn jeder Eintrag eine Gruppe von Elementen statt eines einzelnen ist, kommt der Key auf das Fragment, also brauchst du die lange Form.

Eine Beschreibungsliste ist der klassische Fall: Jeder Eintrag ist ein <dt> und ein <dd>, und ein <dl> sollte diese direkt enthalten.

Klicke auf Reverse, und die Paare tauschen als ganze Einheiten die Plätze, weil jedes Paar seinen eigenen Key hat. Ein umschließendes <div> um jedes Paar würde auch einen Key nehmen und ist in einem dl gültiges HTML, aber es fügt dem Markup eine dritte Ebene hinzu, die ein Fragment draußen lässt.

Fragments in Tabellen

In Tabellen schadet ein überflüssiger Wrapper am meisten. Ein <tr> erwartet Zellen aus <td> und <th> als direkte Kinder. Wenn eine Komponente, die mehrere Zellen zurückgibt, sie in ein <div> packt, behandelt der Browser das div als eine seltsame Zelle, und die Zellen darin passen nicht mehr zur Kopfzeile.

In der Fragment-Zeile steht der Preis unter Price und der Bestand unter Stock. In der div-Zeile sind beide Zellen in die Spalte Price gequetscht, und die Spalte Stock ist leer. In der Entwicklung loggt React außerdem eine Warnung, dass ein <div> kein Kind eines <tr> sein kann; die Vorschau läuft wie ein Produktions-Build, überspringt diese Prüfung also, und du siehst hier das kaputte Layout. Mit Server-Rendering kann derselbe Fehler auch Hydration-Fehler auslösen, weil der HTML-Parser des Browsers das falsch platzierte div verschiebt.

Dieselbe Regel gilt für <ul> und <ol>, die <li>-Elemente enthalten sollten, und für <select>, das <option>-Elemente enthalten sollte. Immer wenn eine Komponente Teile zurückgibt, die direkt in ein solches Elternelement gehören, gib ein Fragment zurück.

Fragments oder Arrays

Eine Komponente kann auch ein Array von Elementen zurückgeben, und React rendert sie der Reihe nach wie ein Fragment. Jedes Element in einem zurückgegebenen Array braucht seinen eigenen Key, genau wie die Ausgabe von map, weil React das Array als Liste behandelt:

function Cells() {
    return [<td key="price">$4</td>, <td key="stock">In stock</td>];
}

Das funktioniert, ist aber unruhiger: Kommas zwischen den Elementen, ein Key an jedem, und eine Klammer, die man leicht übersieht, wenn das Markup wächst. Nutze ein Fragment für eine feste Gruppe von Elementen und behalte Arrays für das, was sie natürlicherweise sind, das Ergebnis eines Mappings über Daten.

Was ein Fragment nicht kann

Weil ein Fragment kein Element rendert, kann es keine Klasse, keinen Style, keinen Event-Handler und keine Ref tragen. <Fragment className="row"> bewirkt nichts Sinnvolles, und die einzige Prop, die React von einem Fragment liest, ist key. Wenn du die Gruppe stylen oder auf Klicks darauf hören willst, brauchst du doch ein echtes Element, und das ist in Ordnung: Wähle eines, das an seiner Stelle gültig ist, etwa ein <tbody> zum Gruppieren von Zeilen oder ein <li> für einen Listeneintrag.

Ein Fragment funktioniert überall, wo ein Element funktioniert, auch beim bedingten Rendern: {show && <>...</>} zeigt oder versteckt die ganze Gruppe auf einmal.

Häufig gestellte Fragen

Was ist ein Fragment in React?

Ein Fragment ist ein Wrapper, mit dem eine Komponente mehrere Elemente als einen Wert zurückgibt, ohne einen DOM-Knoten hinzuzufügen. <><h1 /><p /></> setzt das h1 und das p direkt in das Elternelement.

Was ist der Unterschied zwischen <> und <Fragment>?

Sie erzeugen dasselbe. <>...</> ist die kurze Syntax. <Fragment> ist die lange Form, die du aus react importierst, und die einzige, die einen key annehmen kann, den du brauchst, wenn du Fragments in einer Liste renderst.

Warum ein Fragment statt eines div?

Ein div ist ein echtes Element. Es kann Layouts kaputt machen, die direkte Kinder erwarten (Flex- und Grid-Container, ul, table, tr), und es bläht das DOM auf. Ein Fragment fügt nichts hinzu.

Kann ein Fragment einen className oder onClick haben?

Nein. Ein Fragment rendert kein Element, also gibt es nichts, woran eine Klasse, ein Style oder ein Event-Handler hängen könnte. Die einzige Prop, die es annimmt, ist key. Wenn du etwas davon brauchst, nimm ein echtes Element.

Warum bekomme ich „Adjacent JSX elements must be wrapped in an enclosing tag“?

Eine Komponente hat zwei Geschwisterelemente ohne etwas drumherum zurückgegeben. JSX wird zu einem einzigen Ausdruck kompiliert, also umschließe die Geschwister mit <>...</>.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

LOS GEHT'S