Zum Inhalt springen

JavaScript in JSX

Im letzten Kapitel hast du gesehen, dass JSX-Kommentare geschweifte Klammern verwenden. Aber Kommentare sind nur der Anfang — geschweifte Klammern öffnen ein Fenster zu JavaScript mitten in deinem Markup.

Wenn du ein String-Attribut an JSX übergeben willst, verwendest du einfache oder doppelte Anführungszeichen — genau wie in HTML:

function StudentCard() {
return <img src="dan.jpg" alt="Dan Abramov" />;
}

Hier sind "dan.jpg" und "Dan Abramov" feste Strings. Aber was, wenn du den Namen oder die Bild-URL dynamisch setzen willst? Dann ersetzt du die Anführungszeichen durch geschweifte Klammern:

function StudentCard() {
const name = "Dan Abramov";
const imageUrl = "dan.jpg";
return <img src={imageUrl} alt={name} />;
}

Statt src="dan.jpg" schreibst du src={imageUrl} — und JSX liest den Wert aus der Variable.

Geschweifte Klammern können mehr als nur Variablen auslesen. Du kannst jeden JavaScript-Ausdruck in JSX einbetten — Berechnungen, Methodenaufrufe, Funktionsaufrufe:

function StudentCard() {
const name = "Dan Abramov";
return <h1>{name.toUpperCase()}</h1>;
}

{name.toUpperCase()} ruft die Methode auf und setzt das Ergebnis ("DAN ABRAMOV") in das JSX ein. Auch eigene Funktionen funktionieren:

function formatStudentId(id) {
return "STU-" + id.toString().padStart(4, "0");
}
function StudentCard() {
return <p>ID: {formatStudentId(42)}</p>;
}

{formatStudentId(42)} ruft die Funktion auf und setzt "STU-0042" in das JSX ein.

Auch der Ternary-Operator funktioniert — schließlich ist er ein Ausdruck:

function Greeting() {
const hour = new Date().getHours();
return <p>{hour < 12 ? "Guten Morgen" : "Guten Tag"}, Dan!</p>;
}

{hour < 12 ? "Guten Morgen" : "Guten Tag"} wertet die Bedingung aus und setzt den passenden String ein.

Weil JSX selbst ein JavaScript-Ausdruck ist, kann ein Ternary auch JSX zurückgeben:

function Greeting() {
const hour = new Date().getHours();
return (
<div>
{hour < 12
? <p>Guten Morgen, es ist <strong>{hour} Uhr</strong></p>
: <p>Guten Tag, es ist <strong>{hour} Uhr</strong></p>
}
</div>
);
}

Hier steckt JSX innerhalb von geschweiften Klammern, und in diesem JSX wieder geschweifte Klammern mit {hour}. Das funktioniert, weil JSX nur React.createElement-Aufrufe sind — also ganz normales JavaScript.

Du kannst geschweifte Klammern an genau zwei Stellen in JSX verwenden:

  1. Als Text innerhalb eines JSX-Tags: <h1>{name}</h1>
  2. Als Attributwert direkt nach dem =: src={imageUrl}

Alles andere führt zu einem Fehler. Zum Beispiel kannst du keinen Tag-Namen dynamisch setzen:

// Fehler! Tag-Namen können nicht dynamisch sein
const tag = "h1";
return <{tag}>Hallo</{tag}>;

Und Achtung: Geschweifte Klammern innerhalb von Anführungszeichen werden als normaler Text behandelt:

// Gibt den Text "{imageUrl}" aus, nicht den Wert der Variable!
<img src="{imageUrl}" />

Bisher haben wir nur Strings in geschweifte Klammern gesetzt. Aber viele DOM-Properties sind gar keine Strings — und JSX kann alle JavaScript-Typen übergeben.

ZahlencolSpan erwartet eine Zahl:

<td colSpan={3}>Zusammengefasste Zelle</td>

Booleansdisabled erwartet true oder false:

<button disabled={true}>Gesperrt</button>
<button disabled={false}>Klick mich</button>

Objektestyle erwartet ein Objekt mit CSS-Properties. JavaScript-Objekte verwenden ebenfalls geschweifte Klammern: { color: "#333" }. Um ein Objekt in JSX zu übergeben, brauchst du deshalb zwei Paar geschweifte Klammern — das äußere Paar öffnet das JavaScript-Fenster, das innere definiert das Objekt:

function StudentCard() {
return (
<div style={{ backgroundColor: "#f0f0f0", color: "#333" }}>
<h1>Dan Abramov</h1>
</div>
);
}

{{ sieht auf den ersten Blick nach spezieller Syntax aus — ist es aber nicht. Es ist einfach ein Objekt { backgroundColor: "#f0f0f0", color: "#333" } innerhalb der JSX-Klammern { }.

Die DOM-Property className ist ein String — genau wie das HTML-Attribut class. Im einfachsten Fall übergibst du einen festen String:

<div className="card">...</div>

Aber weil className ein String ist, kannst du mit JavaScript-Ausdrücken beliebig dynamische Klassen bauen.

Ternary — eine Klasse abhängig von einer Bedingung:

<div className={isActive ? "card active" : "card"}>...</div>

Array mit join — mehrere Klassen zusammensetzen:

<div className={["card", "highlighted", "rounded"].join(" ")}>...</div>
// ergibt: className="card highlighted rounded"

Das wird nützlich, wenn manche Klassen bedingt hinzukommen:

<div className={[
"card",
isActive && "active",
isHighlighted && "highlighted",
].filter(Boolean).join(" ")}>...</div>

filter(Boolean) entfernt die false-Werte — übrig bleiben nur die Klassen, deren Bedingung erfüllt ist.

Hilfsfunktion mit Objekt — für komplexere Fälle ist eine Funktion übersichtlicher:

function classNames(classes) {
return Object.entries(classes)
.filter(([, active]) => active)
.map(([name]) => name)
.join(" ");
}
<div className={classNames({
card: true,
active: isActive,
highlighted: isHighlighted,
})}>...</div>

Jeder Schlüssel ist ein Klassenname, der Wert entscheidet, ob er aktiv ist. Das Muster ist so verbreitet, dass es dafür fertige Bibliotheken gibt (z.B. clsx).

Statt Daten über viele Variablen zu verstreuen, kannst du sie in einem Objekt zusammenfassen und daraus in JSX lesen:

const student = {
name: "Dan Abramov",
imageUrl: "dan.jpg",
fachrichtung: "Informatik",
theme: {
backgroundColor: "#f0f0f0",
color: "#333",
},
};
function StudentCard() {
return (
<div style={student.theme}>
<img src={student.imageUrl} alt={student.name} />
<h1>{student.name}</h1>
<p>Fachrichtung: {student.fachrichtung}</p>
</div>
);
}

Alle Daten kommen aus dem student-Objekt:

  • {student.name} → der Name als Text
  • {student.imageUrl} → die Bild-URL als Attribut
  • {student.fachrichtung} → die Fachrichtung als Text
  • style={student.theme} → ein ganzes Style-Objekt als Attribut

So hältst du Daten und Darstellung sauber getrennt — eine Grundidee, die in React immer wieder auftaucht.