JSX ist eine Syntaxerweiterung für JavaScript, mit der du HTML-ähnliches Markup in deinen Code schreibst. React-Komponenten geben JSX zurück, um zu beschreiben, was auf dem Bildschirm erscheinen soll, und ein Build-Tool kompiliert es in gewöhnliche JavaScript-Funktionsaufrufe. Es sieht aus wie HTML, aber einige Regeln sind anders, und mit geschweiften Klammern kannst du jeden JavaScript-Wert ins Markup setzen.
Alles in {} ist JavaScript: eine Eigenschaft, ein Methodenaufruf, sogar map, das aus einem Array Listeneinträge macht. Füge 'design' zum Array skills hinzu, und sowohl die Anzahl als auch die Liste aktualisieren sich.
JSX-Regeln
Gib ein Root-Element zurück
Eine Komponente gibt einen einzigen Wert zurück, also braucht ihr JSX ein einziges Elternelement. Zwei Geschwister auf oberster Ebene sind ein Syntaxfehler. Wenn du kein zusätzliches <div> auf der Seite willst, umschließe sie mit einem Fragment, <>...</>:
// Error: Adjacent JSX elements must be wrapped in an enclosing tag
return (
<h1>Title</h1>
<p>Text</p>
);
// OK: a fragment groups them without adding a DOM element
return (
<>
<h1>Title</h1>
<p>Text</p>
</>
);
Wenn die Gruppe einen key braucht, nutze die lange Form <Fragment key={id}>; siehe Fragments.
Schließe jedes Tag
HTML erlaubt dir, manche Tags offen zu lassen. JSX nicht. Elemente ohne Kinder schließen sich selbst mit />: <img />, <br />, <input /> und deine eigenen Komponenten wie <Avatar />.
Nutze className, htmlFor und camelCase-Attribute
JSX-Attribute werden zu Schlüsseln eines JavaScript-Objekts, also folgen sie der Namensgebung von JavaScript. class und for sind in JavaScript reservierte Wörter, deshalb nutzt JSX className und htmlFor. Attribute aus mehreren Wörtern und jeder Event-Handler sind camelCase: tabIndex, maxLength, autoFocus, onClick, onChange. Zwei Ausnahmen behalten ihre Bindestriche: Attribute aria-* und data-* werden genau wie in HTML geschrieben.
Ändere className="field" zu class="field". Das Label behält seinen Style, weil React das Attribut trotzdem setzt, aber ein Entwicklungs-Build loggt „Invalid DOM property class. Did you mean className?“ Die Vorschau läuft wie ein Produktions-Build, deshalb siehst du diese Warnung hier nicht; nutze className. Ein String-Attribut verwendet Anführungszeichen (type="email"), jeder andere Wert geschweifte Klammern (maxLength={40}, disabled={false}).
Geschweifte Klammern nehmen Ausdrücke, keine Anweisungen
In {} kannst du alles schreiben, was einen Wert ergibt: eine Variable, Arithmetik, einen Funktionsaufruf, einen ternären Operator, &&, ein Template-Literal. Anweisungen wie if, for und const ergeben keinen Wert, also gehören sie nicht dorthin. Erledige die Arbeit vor dem return oder nutze eine Ausdrucksform:
Schau genau hin, bevor du klickst: Die Seite zeigt eine verirrte 0. count && <p>...</p> ergibt 0, wenn der Zähler null ist, und React rendert Zahlen, auch die Null. Ändere es zu count > 0 && <p>You have mail.</p>, und die 0 verschwindet. false, null, undefined und true rendern nichts, deshalb ist ein Boolean links von && sicher. Die Seite zum bedingten Rendern behandelt die Muster.
Inline-Styles verwenden ein Objekt
Das Attribut style nimmt ein JavaScript-Objekt an, keinen CSS-String. Daraus ergibt sich der Look mit „doppelten geschweiften Klammern“: Das äußere Paar bedeutet „hier kommt JavaScript“, das innere ist das Objektliteral. Eigenschaftsnamen sind camelCase (backgroundColor, fontSize), und eine reine Zahl bedeutet bei den meisten Größenangaben Pixel.
Weil der Style ein Objekt ist, kann er wie jeder andere Wert aus State berechnet werden. Ändere fontSize: big ? 24 : 16 zu fontSize: big ? '2em' : '1em': Strings werden mit ihrer Einheit durchgereicht.
Kommentare
Ein Kommentar in JSX steht in geschweiften Klammern: {/* this is a comment */}. HTML-Kommentare (<!-- -->) sind ein Syntaxfehler. Außerhalb des Markups, im Funktionskörper, funktionieren normale //-Kommentare wie gewohnt.
return (
<div>
{/* The header is hidden on small screens */}
<Header />
</div>
);
HTML in JSX umwandeln
HTML in eine Komponente einzufügen ist ein häufiger erster Schritt, und das meiste davon funktioniert. Diese Änderungen musst du normalerweise vornehmen:
classwird zuclassName, undforwird zuhtmlFor.- Leere Tags schließen sich selbst:
<br>wird zu<br />,<img src="a.png">wird zu<img src="a.png" />. style="color: red; font-size: 14px"wird zustyle={{ color: 'red', fontSize: 14 }}.- Event-Attribute nehmen eine Funktion, keinen String:
onclick="save()"wird zuonClick={save}. - Attributnamen werden camelCase:
tabindexwird zutabIndex, undstroke-widthaus SVG wird zustrokeWidth. <!-- comments -->werden zu{/* comments */}.- Mehrere Elemente auf oberster Ebene brauchen ein Elternelement oder ein Fragment.
Online-Konverter von HTML zu JSX erledigen diese Schritte für dich, aber wenn du sie kennst, lassen sich die Fehlermeldungen leicht lesen, falls du einen vergisst.
Was aus JSX kompiliert wird
Browser können JSX nicht ausführen. Ein Compiler (wie Babel, SWC oder Oxc, die Vite und die Frameworks für dich ausführen) macht aus jedem Tag einen Funktionsaufruf aus react/jsx-runtime:
// What you write
const element = <h1 className="title">Hello, {name}</h1>;
const button = <Button size="small">OK</Button>;
// What the compiler produces (roughly)
import { jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime';
const element = _jsxs('h1', { className: 'title', children: ['Hello, ', name] });
const button = _jsx(Button, { size: 'small', children: 'OK' });
Ein kleingeschriebenes Tag wird zu einem String ('h1', ein HTML-Element), ein großgeschriebenes zu einer Referenz auf deine Funktion (Button), Attribute werden zum Props-Objekt, und der Inhalt wird zu children. Ältere Setups kompilierten stattdessen zu React.createElement(type, props, ...children), deshalb beginnen alte Dateien mit import React from 'react', selbst wenn sie React nie erwähnen. Der Aufruf gibt ein einfaches Objekt zurück, das React-Element genannt wird. Du kannst eines loggen:
Die Konsole zeigt, dass heading einfach Daten sind: ein Typ 'h3' und ein Props-Objekt. Deshalb kann JSX auch in Variablen gespeichert, an Funktionen übergeben und aus ihnen zurückgegeben werden.
JSX escapet Text für dich
Jeder String, den du in geschweifte Klammern setzt, wird als Text gerendert, niemals als HTML. Wenn jemand <img src=x onerror=alert(1)> in ein Kommentarfeld tippt, zeigt React diese Zeichen auf dem Bildschirm an, statt ein Bild-Tag zu erzeugen. Das blockiert standardmäßig die häufigste Form von Cross-Site-Scripting (XSS).
Der erste Absatz gibt die Tags als einfache Zeichen aus. Der zweite nutzt dangerouslySetInnerHTML, das das Escapen überspringt und den String als echtes HTML einfügt, also ist „our own“ fett. Der lange Name ist eine Warnung: Übergib dort nur HTML, das du selbst erzeugt oder mit einem Sanitizer wie DOMPurify bereinigt hast. Benutzereingaben dort zu übergeben öffnet die XSS-Lücke wieder, die JSX geschlossen hat.
Häufig gestellte Fragen
Wofür steht JSX?
JSX steht für JavaScript XML. Es ist eine Syntaxerweiterung, mit der du Markup, das wie HTML aussieht, in JavaScript-Code schreibst.
Ist JSX HTML?
Nein. JSX sieht aus wie HTML, wird aber in JavaScript-Funktionsaufrufe kompiliert, die React-Elemente erzeugen. Deshalb nutzt es className statt class, Attributnamen in camelCase und verlangt, dass jedes Tag geschlossen wird.
Kann ich React ohne JSX verwenden?
Ja. JSX ist optional: Du kannst createElement('h1', { className: 'title' }, 'Hello') aus react direkt aufrufen. Fast jede React-Codebasis nutzt JSX, weil verschachteltes Markup so viel leichter zu lesen ist.
Warum kann ich in JSX keine if-Anweisung verwenden?
Geschweifte Klammern in JSX nehmen Ausdrücke an, also Dinge, die einen Wert ergeben, und if ist eine Anweisung. Nutze einen ternären Operator (cond ? a : b), && oder berechne den Wert vor dem return in einer Variablen.
Wie schreibe ich einen Kommentar in JSX?
Setze einen JavaScript-Kommentar in geschweifte Klammern: {/* so */}. HTML-Kommentare (<!-- -->) sind in JSX ein Syntaxfehler.