7.5 React-Grundlagen: Datenfluss und Formulare
Nach dieser Einheit kannst du:
- den Einweg-Datenfluss von React beschreiben: Props nach unten, Events über Callback-Props nach oben.
- begründet entscheiden, wo ein Zustand wohnt, und gemeinsam genutzten Zustand zum nächstgemeinsamen Vorfahren heben.
- Callback-Props typisieren.
- Formulare als controlled Components mit Validierung bauen und begründen, wann ein uncontrolled Feld mit
useRefgenügt.
In einer Wohngemeinschaft hängt die Einkaufsliste am Kühlschrank, nicht in der Jackentasche einer Mitbewohnerin. Nur so sehen alle, was fehlt, und wer Milch braucht, schreibt sie dort dazu. Hätte jede ihre eigene Liste, käme die Milch dreimal nach Hause und das Brot gar nicht. In React stellt sich dieselbe Frage bei jedem Entwurf: Wo hängt die Liste? Zustand, den mehrere Komponenten brauchen, hängt beim nächstgemeinsamen Vorfahren, und die Kinder melden Änderungen dorthin.
flowchart TD
accTitle: Gemeinsamer Zustand wohnt beim gemeinsamen Vorfahren
fridge["JobDashboard<br/>hält jobs und searchText"] -- "searchText, onSearch" --> filter["FilterField"]
fridge -- "gefilterte jobs, onCancel" --> list["JobList"]
fridge -- "jobs.length" --> header["Header"]
Abb. 7.20: Die “Einkaufsliste” hängt beim gemeinsamen Vorfahren, die Kinder lesen und melden (eigene Darstellung).
In Einheit 7.4 hatte jede Komponente ihren privaten State. Diese Einheit verbindet Komponenten: Sie zeigt, wie Daten durch die Hierarchie fließen und wie Formulare Benutzereingaben in den State bringen.
Begriffe vorab
Abschnitt betitelt „Begriffe vorab“- Einweg-Datenfluss: Daten fließen in React nur von Eltern- zu Kindkomponenten.
- Callback-Prop: ein Prop, dessen Wert eine Funktion ist, über die ein Kind den Eltern etwas meldet, etwa
onCancel. - State heben (lifting state up): Zustand aus einem Kind in den gemeinsamen Vorfahren verschieben, damit mehrere Komponenten ihn nutzen.
- Controlled Component: ein Formularfeld, dessen Wert aus dem React-State kommt.
- Ref: eine Referenz auf ein DOM-Element, über die React ein Feld bei Bedarf ausliest.
Datenfluss: Props runter, Events rauf
Abschnitt betitelt „Datenfluss: Props runter, Events rauf“In React fließen Daten in eine Richtung: von Eltern- zu Kindkomponenten über Props. Will ein Kind etwas ändern, ruft es eine Funktion auf, die ihm die Eltern als Prop mitgegeben haben:
flowchart TD
accTitle: Props runter, Events rauf am Beispiel JobDashboard
parent["JobDashboard<br/>hält den State"] -- "Props runter: jobs, onCancel" --> child["JobList"]
child -- "Events rauf: onCancel(id)" --> parent
Abb. 7.21: Die Daten fließen nach unten, die Meldung über die Funktion nach oben (eigene Darstellung).
function JobDashboard() { const [jobs, setJobs] = useState<Job[]>(initialJobs);
function cancelJob(id: number) { setJobs(jobs.filter((j) => j.id !== id)); }
return <JobList jobs={jobs} onCancel={cancelJob} />;}
function JobList({ jobs, onCancel }: { jobs: Job[]; onCancel: (id: number) => void }) { return ( <ul> {jobs.map((job) => ( <li key={job.id}> {job.filename} <button onClick={() => onCancel(job.id)}>cancel</button> </li> ))} </ul> );}Beispielprojekt: 07_react_grundlagen_examples/ex16_job_dashboard
JobList kennt den State nicht und ändert ihn nicht; sie bekommt die Liste und eine Funktion. Den eigentlichen Zustand ändert nur JobDashboard, über ihren Setter.
Damit stellt sich bei jedem Entwurf dieselbe Frage: Wo lebt welcher Zustand? Die Antwort folgt einer Regel: beim nächstgemeinsamen Vorfahren aller Komponenten, die ihn brauchen. Brauchen Filterfeld und Liste denselben Suchtext, gehört er in die gemeinsame Elternkomponente und wandert als Prop nach unten (lifting state up). Zustand, den nur eine Komponente braucht, bleibt bei ihr. Diese Entwurfsfrage entscheidet mehr über die Qualität einer React-Anwendung als jede Syntax.
Beachte die Typisierung der Callback-Prop: onCancel: (id: number) => void ist der Vertrag in beide Richtungen. Die Elternkomponente muss eine passende Funktion liefern, das Kind darf sie nur mit einer Zahl aufrufen; beides prüft der Compiler, bevor die Seite lädt.
Wo begegnet dir das? In jedem Webshop mit Warenkorb-Symbol in der Kopfzeile: Legst du in der Produktliste etwas in den Warenkorb, ändert sich die Zahl oben sofort. Kopfzeile und Produktliste sind Geschwister, also wohnt der Warenkorb in einem gemeinsamen Vorfahren.
Auflösung
Der Suchtext wohnt in App, dem nächstgemeinsamen Vorfahren. FilterField bekommt searchText und onSearchChange, JobList bekommt die gefilterte Liste (in App beim Rendern berechnet) und Header deren Länge. Die gefilterte Liste ist kein eigener State, sondern wird aus Aufträgen und Suchtext abgeleitet.
Formulare: controlled und uncontrolled
Abschnitt betitelt „Formulare: controlled und uncontrolled“Formulare sind das Haupteinfallstor für Benutzereingaben und in React ein eigenes Thema, weil es zwei legitime Ansätze gibt.
Controlled Components
Abschnitt betitelt „Controlled Components“Beim kontrollierten Formularfeld ist React die einzige Quelle der Wahrheit: Der Feldwert kommt aus dem State (value), jede Eingabe läuft über onChange in den State zurück.
function NewJobForm({ onCreate }: { onCreate: (job: NewJob) => void }) { const [filename, setFilename] = useState(""); const [preset, setPreset] = useState("web-1080p");
function handleSubmit(event: React.FormEvent) { event.preventDefault(); // stop the browser's page reload if (filename.trim() === "") return; onCreate({ filename: filename.trim(), preset }); setFilename(""); // reset the field }
return ( <form onSubmit={handleSubmit}> <input value={filename} onChange={(e) => setFilename(e.target.value)} /> <select value={preset} onChange={(e) => setPreset(e.target.value)}> <option value="web-1080p">Web 1080p</option> <option value="web-4k">Web 4K</option> </select> <button type="submit" disabled={filename.trim() === ""}>Create job</button> </form> );}Beispielprojekt: 07_react_grundlagen_examples/ex17_new_job_form
NewJob ist der Eingabetyp aus Kapitel 6: Pick<Job, "filename" | "preset">. Der Preis des kontrollierten Felds sind ein State und ein Handler pro Feld. Der Gewinn ist Kontrolle in Echtzeit: Der Knopf ist deaktiviert, solange die Eingabe ungültig ist; eine Live-Validierung oder Zeichenzählung wäre eine Zeile; der State ist jederzeit der komplette, aktuelle Formularinhalt.
flowchart LR
accTitle: Der Kreislauf eines kontrollierten Felds
state["State<br/>filename"] -- "value" --> input["input"]
input -- "onChange" --> setter["setFilename(...)"]
setter --> state
Abb. 7.22: Beim kontrollierten Feld fließt jeder Tastendruck durch den State zurück ins Feld (eigene Darstellung).
Zwei Details: event.preventDefault() im Submit-Handler verhindert das Neuladen der Seite (das Standardverhalten von HTML-Formularen), und Checkboxen lesen sich über e.target.checked statt value.
Uncontrolled Components
Abschnitt betitelt „Uncontrolled Components“Beim unkontrollierten Feld verwaltet der Browser den Wert selbst, wie in klassischem HTML; React liest ihn nur bei Bedarf aus, über eine Ref auf das DOM-Element. useRef ist ein weiterer Hook; Einheit 7.6 stellt ihn genauer vor.
function SearchForm({ onSearch }: { onSearch: (term: string) => void }) { const inputRef = useRef<HTMLInputElement>(null);
function handleSubmit(event: React.FormEvent) { event.preventDefault(); onSearch(inputRef.current?.value ?? ""); }
return ( <form onSubmit={handleSubmit}> <input ref={inputRef} defaultValue="" placeholder="search" /> <button type="submit">Search</button> </form> );}Beispielprojekt: 07_react_grundlagen_examples/ex18_search_form
Statt value gibt es höchstens ein defaultValue (den Startwert); kein State, kein onChange, kein Neu-Rendern pro Tastendruck.
Wann welches?
Abschnitt betitelt „Wann welches?“| Kriterium | controlled | uncontrolled |
|---|---|---|
| Wert liegt in | React-State | DOM |
| Live-Validierung, abhängige Felder | natürlich | umständlich |
| Feld zurücksetzen oder programmatisch füllen | einfach (Setter) | über die Ref |
| Aufwand pro Feld | State + Handler | eine Ref |
| Neu-Rendern bei jedem Tastendruck | ja | nein |
Faustregel: Controlled ist der Standard dieses Jahres, weil Validierung und Reaktionen auf Eingaben ständig gebraucht werden. Uncontrolled ist die berechtigte Abkürzung für einfache Fälle nach dem Muster “ein Feld, ein Absenden, dazwischen egal”. Wichtig ist, sich pro Feld zu entscheiden: Ein value ohne onChange erzeugt ein eingefrorenes Feld (React warnt in der Konsole), und das nachträgliche Umschalten zwischen beiden Modi quittiert React ebenfalls mit einer Warnung.
Auflösung
(a), (c) und (d) controlled: Der Zähler und der aktive Knopf leiten sich bei jedem Tastendruck aus dem State ab, und Leeren ist ein Setter-Aufruf. (b) darf uncontrolled sein: ein Feld, ein Absenden, dazwischen keine Reaktion nötig. Controlled wäre auch dort richtig, nur etwas mehr Code.
Stolperfallen
Abschnitt betitelt „Stolperfallen“- Zustand im falschen Kind: Filterfeld und Liste haben je einen eigenen Suchtext, die beiden laufen auseinander. Der Zustand gehört in den gemeinsamen Vorfahren.
- Callback im Rumpf aufgerufen:
onCancel(job.id)direkt im JSX statt in() => onCancel(job.id)läuft bei jedem Rendern. valueohneonChange: Das Feld ist eingefroren; React warnt in der Konsole.preventDefault()vergessen: Das Formular lädt die Seite neu, der State ist weg.- Gefilterte Liste als eigener State: Sie lässt sich aus Liste und Suchtext berechnen und läuft sonst auseinander.
Zusatzmaterialien
Abschnitt betitelt „Zusatzmaterialien“- react.dev: Sharing state between components - State heben Schritt für Schritt an einem Akkordeon.
- react.dev: Thinking in React - von der Skizze zur Komponentenhierarchie.
- react.dev:
<input>- controlled und uncontrolled Felder,value,defaultValueund die Warnungen. - react.dev: Tutorial: Tic-Tac-Toe - ein Spiel von Grund auf, mit “State heben” an einem durchgehenden Beispiel.
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 Codebeispiele 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:
- den Einweg-Datenfluss von React beschreiben: Props nach unten, Events über Callback-Props nach oben.
- begründet entscheiden, wo ein Zustand wohnt, und gemeinsam genutzten Zustand zum nächstgemeinsamen Vorfahren heben.
- Callback-Props typisieren.
- Formulare als controlled Components mit Validierung bauen und begründen, wann ein uncontrolled Feld mit
useRefgenügt.
Passende Übungen
Abschnitt betitelt „Passende Übungen“- Aufgabe 07-4a - State-Training, Stufen Wesentlich_vollständig, PlusPlus und MandalorianPlus
Quellen
Abschnitt betitelt „Quellen“- Einweg-Datenfluss, State heben → react.dev: Sharing state between components, Thinking in React
- Controlled und uncontrolled Felder,
defaultValue, Warnungen → react.dev:<input> useRef→ react.dev: useRefpreventDefault→ MDN: Event: preventDefault() method- Warnung bei
valueohneonChange→ eigener Test im Beispielprojektex17_new_job_form(Oktober 2026) - Abb. 7.20 (gemeinsamer Vorfahr), Abb. 7.21 (Props runter, Events rauf), Abb. 7.22 (kontrolliertes Feld) → eigene Darstellung, alle als Mermaid-Diagramm
Autoren
Abschnitt betitelt „Autoren“- Oliver Maurhart (MAO)
- Michael Gabriel (GAM)
CC-BY-SA