7.2 React-Grundlagen: JSX und Komponenten
Nach dieser Einheit kannst du:
- die JavaScript-Sprachmittel nennen, die React ständig verwendet, und ternären Operator,
&&und Funktionen als Werte sicher lesen. - JSX nach seinen Spielregeln schreiben: Ausdrücke in geschweiften Klammern,
className, geschlossene Tags, ein Wurzelelement oder Fragment. - Funktionskomponenten in eigenen Dateien anlegen, benannt exportieren und in anderen Komponenten verwenden.
- entscheiden, ob ein Stück Code eine Komponente oder eine gewöhnliche Funktion sein soll.
Eine Seite aus Legosteinen: Ein Stein mit vier Noppen wird einmal entworfen und dann hundertfach verbaut, mal rot, mal blau, mal als Dach, mal als Wand. Niemand gießt für jede Stelle einen eigenen Stein. Genau so entsteht eine React-Oberfläche: Ein Baustein, die Komponente, wird einmal geschrieben und danach mit unterschiedlichen Daten immer wieder verwendet.
flowchart TD
accTitle: Eine Seite aus wiederverwendbaren Komponenten
app["App"] --> header["Header"]
app --> list["JobList"]
list --> c1["JobCard<br/>intro.mp4"]
list --> c2["JobCard<br/>outro.mp4"]
list --> c3["JobCard<br/>trailer.mp4"]
Abb. 7.6: Eine Komponente, dreimal verwendet, jedes Mal mit anderen Daten (eigene Darstellung).
Die Schreibweise, in der Komponenten ihre Oberfläche beschreiben, heißt JSX. Sie sieht aus wie HTML, ist aber TypeScript, und sie verwendet konsequent die modernen Sprachmittel aus Kapitel 1. Deshalb beginnt diese Einheit mit einer kurzen Prüfliste der JavaScript-Grundlagen, dann folgen JSX und Komponenten. Durchgehendes Beispiel des Kapitels ist wieder die Render-Farm aus Kapitel 6: Aufträge (jobs) mit Dateiname, Zustand und Fortschritt.
Begriffe vorab
Abschnitt betitelt „Begriffe vorab“- JSX: HTML-artige Syntax mitten im TypeScript; Dateien mit JSX enden auf
.tsx. - Ausdruck: ein Stück Code, das einen Wert ergibt (
count + 1,a ? b : c); eine Anweisung wieifergibt keinen. - Fragment:
<>...</>, eine unsichtbare Klammer um mehrere Elemente, die kein HTML-Element erzeugt. - Funktionskomponente: eine Funktion, deren Name groß beginnt und die JSX zurückgibt.
- Benannter Export:
export function JobCard, beim Import steht der Name in geschweiften Klammern fest.
Was React aus JavaScript voraussetzt
Abschnitt betitelt „Was React aus JavaScript voraussetzt“React erfindet keine neue Sprache. Wer die Sprachmittel aus Kapitel 1 sicher beherrscht, liest React-Code flüssig; wer nicht, hält gewöhnliches JavaScript für React-Magie. Die Übersicht ist deine Prüfliste; die Beispiele danach sind bewusst reines JavaScript, weil es hier um Sprachmittel geht und noch nicht um Komponenten.
| Sprachmittel | Wo es in React ständig vorkommt | Einheit in Kapitel 1 |
|---|---|---|
| Arrow Functions | Event-Handler, Callbacks in map, Setter-Funktionen | 1.2, Funktionen und Arrow Functions |
| Destructuring | Props entpacken, const [value, setValue] = useState(...) | 1.4, Destructuring |
| Spread und Rest | State unverändert kopieren und ergänzen | 1.4, Spread und Rest |
map, filter, reduce | Listen rendern, Werte aus Daten ableiten | 1.2, Arrays und ihre Methoden |
Module (import/export) | jede Komponente in einer eigenen Datei | 1.4, Module |
Optional Chaining ?. und ?? | Daten, die es noch nicht gibt | 1.4, Optional Chaining |
Drei Kleinigkeiten daraus tauchen in JSX so häufig auf, dass sie hier noch einmal ausdrücklich stehen.
Der ternäre Operator ist die Ausdrucksform der Verzweigung. Deshalb kommt er in React so oft vor: In JSX sind nur Ausdrücke erlaubt, ein if ist keiner.
const age = 20;const status = age >= 18 ? "volljährig" : "minderjährig";Der &&-Operator ist die Kurzform für “nur wenn”: Er wertet die rechte Seite nur aus, wenn die linke wahr ist.
const isFailed = true;isFailed && console.log("needs attention"); // short for: if (isFailed) { ... }Funktionen als Werte sind die Grundlage jedes Event-Handlers: Eine Funktion kann in einer Variablen stehen und als Argument übergeben werden, ohne aufgerufen zu werden.
const double = (n) => n * 2;const apply = (fn, value) => fn(value); // fn is a parameter, not a callapply(double, 21); // 42Beispielprojekt: 07_react_grundlagen_examples/ex04_js_for_react
Der Unterschied zwischen double (die Funktion) und double(21) (ihr Ergebnis) wird in Einheit 7.3 bei den Events zum häufigsten Anfängerfehler überhaupt.
flowchart LR
accTitle: Funktion übergeben oder Ergebnis übergeben
fn["double<br/>die Funktion"] -- "übergeben" --> later["wird später<br/>aufgerufen"]
fnCall["double(21)<br/>ein Aufruf"] -- "läuft sofort" --> value["übergeben wird<br/>der Wert 42"]
Abb. 7.7: Ohne Klammern wandert die Funktion weiter, mit Klammern nur ihr Ergebnis (eigene Darstellung).
JSX: HTML-artige Syntax in TypeScript
Abschnitt betitelt „JSX: HTML-artige Syntax in TypeScript“Eine Komponente ist eine Funktion, die Oberfläche zurückgibt. Die Schreibweise dafür ist JSX: HTML-artige Syntax mitten im TypeScript, in die du mit geschweiften Klammern beliebige Ausdrücke einbettest.
function Greeting() { const character = "Iron Man"; return <h1>Hello {character.toUpperCase()}</h1>;}Alles zwischen { und } ist gewöhnliches TypeScript: Variablen, Rechnungen, Funktionsaufrufe, ternäre Operatoren. Das Ergebnis wird an dieser Stelle gerendert, im Beispiel <h1>Hello IRON MAN</h1>.
Die JSX-Spielregeln:
- Komponentennamen beginnen groß (
JobCard); kleingeschriebene Tags hält React für HTML-Elemente. {...}bettet Ausdrücke ein. Anweisungen (if,for) gehören nicht hinein, wohl aber deren Ausdrucksformen (ternärer Operator,&&,map).- Statt
classheißt das AttributclassName(classist in JavaScript reserviert); stattforbei Labels heißt eshtmlFor. - Jedes Element wird geschlossen, auch die in HTML nachlässig behandelten:
<br />,<img ... />. - Eine Komponente gibt ein Wurzelelement zurück; mehrere Geschwister umschließt ein Fragment
<>...</>.
Der letzte Punkt ist der häufigste Anfängerfehler. Das hier ist ungültig, weil zwei <div> nebeneinander zurückgegeben werden:
// does not compile: two root elementsreturn ( <div>...</div> <div>...</div>);Ein zusätzliches <div> drumherum würde zwar helfen, verändert aber die HTML-Struktur und damit womöglich das CSS. Das Fragment löst das Problem, ohne ein Element zu erzeugen:
return ( <> <div>...</div> <div>...</div> </>);JSX-Ausdrücke sind gewöhnliche Werte: Sie lassen sich in Variablen ablegen, aus Funktionen zurückgeben und in Arrays sammeln.
function Profile() { const username = "Bart"; const heading = <h2>{username}</h2>; // a value like any other return <div>{heading}</div>;}Genauer erklärt: Was hier wie HTML aussieht, ist keines. Vite übersetzt jedes JSX-Element in einen Funktionsaufruf, der ein einfaches Objekt erzeugt, ungefähr { type: "h2", props: { children: "Bart" } }. Genau diese Objekte bilden den Virtual DOM aus Einheit 7.1. Daraus folgt auch, warum nur ein Wurzelelement erlaubt ist: Eine Funktion kann genau einen Wert zurückgeben, und zwei Geschwisterelemente wären zwei.
flowchart LR
accTitle: Aus JSX wird ein Objekt
jsx["JSX<br/><h2>Bart</h2>"] --> fnCall["Funktionsaufruf<br/>beim Übersetzen"]
fnCall --> obj["Objekt<br/>type: h2<br/>children: Bart"]
obj --> vdom["Teil des<br/>Virtual DOM"]
Abb. 7.8: JSX ist eine Kurzschrift für Objekte, aus denen der Virtual DOM besteht (eigene Darstellung).
Ein Sonderfall der geschweiften Klammern sind Objekte in JSX. Weil Objektliterale selbst geschweifte Klammern haben, entsteht ein doppeltes Paar, das äußere für “hier kommt TypeScript”, das innere für das Objekt:
<li style={{ color: "darkgreen", fontWeight: "bold" }}>Gandalf</li>Beispielprojekt: 07_react_grundlagen_examples/ex05_jsx_rules
Inline-Styles sind der Regelfall für diese Schreibweise, aber nicht der Regelfall für Gestaltung: Für alles Wiederkehrende bleiben CSS-Klassen über className die bessere Wahl.
Zur Schreibweise: Im Kurs formatiert Biome den Code (Einheit 1.1), und seine Voreinstellung setzt doppelte Anführungszeichen, für JSX-Attribute wie für gewöhnliche Strings. Deshalb stehen in allen Beispielen doppelte Anführungszeichen. Wer bestehendes HTML übernehmen will, spart sich die Handarbeit mit dem Konverter transform.tools/html-to-jsx: Er ersetzt class durch className und schließt offene Tags.
Auflösung
classmussclassNameheißen.<br>muss geschlossen werden:<br />.- Drei Geschwister ohne gemeinsames Wurzelelement: Ein Fragment
<>...</>gehört drumherum. jobCounterbeginnt klein und wird deshalb als HTML-Element behandelt; als Komponente muss esJobCounterheißen.
Komponenten
Abschnitt betitelt „Komponenten“Eine React-Anwendung besteht aus Komponenten. Historisch gab es sie in zwei Bauformen, als Klasse und als Funktion; heute sind Funktionskomponenten der Standard, und nur sie kommen in diesem Kurs vor. Klassenkomponenten begegnen dir höchstens in altem Code.
interface JobCardProps { filename: string; progress: number; // 0 to 1}
export function JobCard({ filename, progress }: JobCardProps) { return ( <section className="job-card"> <h3>{filename}</h3> <p>{Math.round(progress * 100)} % rendered</p> </section> );}Verwendet wird sie wie ein eigenes HTML-Element, in der Datei, die sie importiert:
import { JobCard } from "./components/JobCard";
export default function App() { return ( <main> <JobCard filename="intro.mp4" progress={0.62} /> <JobCard filename="outro.mp4" progress={0.1} /> </main> );}Beispielprojekt: 07_react_grundlagen_examples/ex07_job_card
Die Attribute filename und progress sind die Props der Komponente, ihre Eingabedaten; das interface darüber beschreibt, welche sie erwartet. Props bekommen in Einheit 7.3 einen eigenen Abschnitt. Die Regeln für Komponenten:
- Eine Komponente ist eine Funktion, die JSX zurückgibt.
- Ihr Name beginnt mit einem Großbuchstaben. React unterscheidet daran Komponenten von HTML-Elementen.
- Sie wohnt in einer eigenen Datei unter
src/components/, benannt wie die Komponente (JobCard.tsx). - Sie wird exportiert, damit andere Dateien sie importieren können.
- Sie bekommt ihre Daten ausschließlich über Props und liest niemals aus dem DOM.
flowchart LR
accTitle: Datei, Export und Verwendung einer Komponente
file["components/JobCard.tsx<br/>export function JobCard"] -- "import { JobCard }" --> app["App.tsx"]
app -- "<JobCard filename=... />" --> c1["Karte 1"]
app -- "<JobCard filename=... />" --> c2["Karte 2"]
Abb. 7.9: Eine Datei pro Komponente, ein Import, beliebig viele Verwendungen (eigene Darstellung).
Für den Export gibt es zwei Formen: export function JobCard() {...} (benannt) und export default function JobCard() {...} (Standardexport). Im Kurs gilt: benannter Export für alle Komponenten, weil der Name dann beim Import feststeht und Tippfehler auffallen; der Standardexport bleibt der Wurzelkomponente App vorbehalten, weil Vite sie so erzeugt. Beide Formen sind verbreitet, und du wirst beiden begegnen.
Wo begegnet dir das? In jeder größeren Website: Die Produktkacheln eines Online-Shops, die Beitragskarten eines sozialen Netzwerks oder die Videovorschauen einer Streamingseite sind jeweils ein und derselbe Baustein, hundertfach mit anderen Daten gerendert.
Nicht jede Funktion in einer React-Datei ist eine Komponente. Die Abgrenzung:
| Situation | Was es sein soll |
|---|---|
| wiederverwendbarer Oberflächenbaustein mit Props | Komponente |
| braucht eigenen Zustand oder Hooks | Komponente |
| berechnet nur einen Wert (Datum formatieren, Summe bilden) | gewöhnliche Funktion |
| erzeugt ein kleines Stück JSX innerhalb einer Komponente | gewöhnliche Funktion oder Variable |
Faustregel: Eine Komponente ist, was in JSX als <Name /> auftaucht. Alles andere ist eine gewöhnliche Funktion, und die gehört, wenn sie nichts mit der Anzeige zu tun hat, in eine eigene Datei außerhalb von components/.
Auflösung
(a) und (c) sind gewöhnliche Funktionen: Sie berechnen nur einen Wert und geben kein JSX zurück. (b) und (d) sind Komponenten (ProgressBar, CancelButton): wiederverwendbare Oberflächenbausteine, die in JSX als <Name /> auftauchen.
Stolperfallen
Abschnitt betitelt „Stolperfallen“- Zwei Wurzelelemente:
return (<div /> <div />)kompiliert nicht; ein Fragment<>...</>gehört drumherum. classstattclassName,<br>ohne Schrägstrich: die JSX-Klassiker der ersten Woche.- Komponente kleingeschrieben:
<jobCard />hält React für ein HTML-Element; TypeScript meldet beim Build, dass es dieses Element nicht gibt. ifin geschweiften Klammern: In JSX sind nur Ausdrücke erlaubt; der ternäre Operator ist die Ausdrucksform.- Komponente nicht exportiert: Der Import in
App.tsxschlägt fehl.
Zusatzmaterialien
Abschnitt betitelt „Zusatzmaterialien“- react.dev: Your first component - Komponenten definieren und verschachteln, mit Aufgaben zum Ausprobieren.
- react.dev: Importing and exporting components - benannter Export und Standardexport im Vergleich.
- transform.tools/html-to-jsx - wandelt HTML-Schnipsel in gültiges JSX um.
Zum Anhören
Abschnitt betitelt „Zum Anhören“Du kannst dir diese Einheit kostenlos mit der Vorlesefunktion deines Browsers oder Betriebssystems vorlesen lassen (etwa „Laut vorlesen” in Edge), ohne Konto und ohne Upload; die JSX-Beispiele liest du dabei am Bildschirm mit. Freiwillig kannst du mit Google NotebookLM (Google-Konto nötig) aus diesem öffentlichen Text eine gesprochene Zusammenfassung erzeugen, auch auf Deutsch.
Lernergebnisse
Abschnitt betitelt „Lernergebnisse“Du kannst jetzt:
- die JavaScript-Sprachmittel nennen, die React ständig verwendet, und ternären Operator,
&&und Funktionen als Werte sicher lesen. - JSX nach seinen Spielregeln schreiben: Ausdrücke in geschweiften Klammern,
className, geschlossene Tags, ein Wurzelelement oder Fragment. - Funktionskomponenten in eigenen Dateien anlegen, benannt exportieren und in anderen Komponenten verwenden.
- entscheiden, ob ein Stück Code eine Komponente oder eine gewöhnliche Funktion sein soll.
Passende Übungen
Abschnitt betitelt „Passende Übungen“- Aufgabe 07-1a - Komponenten-Baukasten, Stufe Wesentlich_überwiegend
Quellen
Abschnitt betitelt „Quellen“- JSX-Regeln,
className, Fragment → react.dev: Writing markup with JSX, JavaScript in JSX with curly braces - Funktionskomponenten, Export → react.dev: Your first component, Importing and exporting components
- JSX als Objekte → react.dev: createElement
- Doppelte Anführungszeichen als Voreinstellung von Biome → eigener Test mit Biome 2.5.15 (Oktober 2026)
- Compiler-Meldungen zu zwei Wurzelelementen und zu
<jobCard />→ eigener Test mit TypeScript 6.0.3 aus der Vite-Vorlage (Oktober 2026), siehe README der Beispielprojekte - Abb. 7.6 (Komponentenbaum), Abb. 7.7 (Funktion oder Ergebnis), Abb. 7.8 (JSX als Objekt), Abb. 7.9 (Datei, Export, Verwendung) → eigene Darstellung, alle als Mermaid-Diagramm
Autoren
Abschnitt betitelt „Autoren“- Oliver Maurhart (MAO)
- Michael Gabriel (GAM)
CC-BY-SA