Aufgabe 12 - State-Training
Aufgabe 12 - State-Training
Abschnitt betitelt „Aufgabe 12 - State-Training“Worum geht es?
Abschnitt betitelt „Worum geht es?“Der Umgang mit State ist die zentrale Denkumstellung bei React. An vier kleinen Komponenten trainieren Sie, Zustand richtig zu modellieren (was ist State, was ist ableitbar?), immutabel zu aktualisieren und an die richtige Stelle der Hierarchie zu heben (siehe Kapitel React-Grundlagen).
Was Sie dafür brauchen
Abschnitt betitelt „Was Sie dafür brauchen“- Kapitel React-Grundlagen, Abschnitte State und Datenfluss.
- Das Next.js-Projekt aus Aufgabe 11 (oder ein frisches über
npx create-next-app@latest, siehe dort); ein Vorgriff auf Kapitel 8. Next.js I - Struktur und Routing. Ihre Übungskomponenten entstehen darin unterapp/.
Welche Kompetenzen Sie erwerben und zeigen
Abschnitt betitelt „Welche Kompetenzen Sie erwerben und zeigen“- Sie entscheiden begründet, welche Werte State sind und welche berechnet werden.
- Sie aktualisieren State immutabel, insbesondere Arrays und Objekte.
- Sie heben gemeinsamen State in den nächstgemeinsamen Vorfahren.
Pädagogische Einordnung
Abschnitt betitelt „Pädagogische Einordnung“- Reproduktion: das
useState-Muster an einfachen Komponenten anwenden (Teil A). - Reorganisation und Transfer: Zustandsmodelle analysieren und Aktualisierungsregeln übertragen (Teile B und C).
- Reflexion, Problemlösung und Urteilsbildung: eine Hierarchie-Entscheidung treffen und verteidigen (Teil D).
Arbeitsaufträge
Abschnitt betitelt „Arbeitsaufträge“Die Übung ist auf etwa zwei Stunden ausgelegt. Teil D ist der Expertenteil.
So richten Sie die Übungsseite ein (einmal am Anfang, dann geht es los):
- Legen Sie im Projekt den Ordner
app/uebung/an und darin eine Dateipage.tsx. Diese Seite erreichen Sie im Browser unterhttp://localhost:3000/uebung, sobald der Entwicklungsserver läuft (npm run dev). - Jede der vier Komponenten schreiben Sie in eine eigene Datei, etwa
app/uebung/Thumbs.tsx. Wichtig: Jede Komponente, dieuseStateverwendet, braucht in Next.js ganz oben in der Datei die Zeile"use client";(sonst läuft sie als Server-Komponente unduseStatebricht ab). Diese Fehlermeldung werden Sie mindestens einmal sehen; sie ist der häufigste Stolperstein in dieser Übung. - In
page.tsximportieren Sie die Komponenten und rendern sie untereinander. So wächst die Seite Stück für Stück:
import { Thumbs } from "./Thumbs";import { CharacterCounter } from "./CharacterCounter";
export default function UebungPage() { return ( <main> <Thumbs /> <CharacterCounter /> {/* the other components get added here as you build them */} </main> );}Arbeiten Sie eine Komponente nach der anderen ab: Datei anlegen, in page.tsx einhängen, im Browser ausprobieren, dann die nächste.
Teil A - Zwei einfache Komponenten
Abschnitt betitelt „Teil A - Zwei einfache Komponenten“Thumbs- ein Daumen-hoch/-runter-Zähler. Konkret: zwei Buttons und dazwischen eine Zahl, die die Differenz zeigt. Schritte:- Legen Sie mit
useStatefest, was Sie speichern. Treffen Sie jetzt die Entscheidung: ein einziger State (die Differenz) oder zwei getrennte States (upunddown)? Schreiben Sie Ihre Wahl und die Begründung als Kommentar über die Komponente (Tipp: Was müssten Sie ändern, wenn später “wie viele Stimmen insgesamt?” dazukäme? Das ist ein Argument für zwei States). - Der Klick auf “hoch” erhöht, der Klick auf “runter” verringert. Verwenden Sie die Setter-Funktionsform:
setUp((current) => current + 1). - Zeigen Sie die Differenz an. Wenn Sie zwei States gewählt haben, wird sie berechnet (
up - down), nicht gespeichert.
- Legen Sie mit
CharacterCounter- ein Textfeld mit Live-Zeichenzähler wie bei einer Kurznachricht. Schritte:- Ein
<textarea>als controlled component: Seinvaluekommt aus dem State,onChangeschreibt jede Eingabe zurück in den State (siehe Kapitel React-Grundlagen, Abschnitt Formulare). - Darunter live “42 / 280 Zeichen”. Die aktuelle Länge ist
text.length, also abgeleitet, kein eigener State. - Ab 260 Zeichen bekommt die Anzeige eine Warnfarbe. Leiten Sie die CSS-Klasse aus dem State ab:
className={text.length > 260 ? "warn" : ""}. Keindocument.querySelector, kein manuelles Umfärben.
- Ein
Teil B - Arrays im State
Abschnitt betitelt „Teil B - Arrays im State“ShoppingList - eine Einkaufsliste: ein Eingabefeld plus “Hinzufügen”-Button hängt einen Eintrag an, ein Klick auf einen Eintrag entfernt ihn wieder. Schritte:
- Zwei States: der aktuelle Text des Eingabefelds (String) und die Liste der Einträge (
string[]). Fügen Sie immutabel hinzu und entfernen Sie immutabel:setItems([...items, newItem])zum Anhängen,setItems(items.filter((item) => item !== clicked))zum Entfernen. - Pflicht-Experiment: Bauen Sie das Hinzufügen absichtlich einmal falsch mit
items.push(newItem)(ohne Setter). Beobachten Sie, dass die Anzeige sich nicht aktualisiert, und beschreiben Sie im Kommentar, warum React die Änderung nicht bemerkt. Danach zurück zur korrekten Version. - Leere Eingaben sollen nicht in die Liste: Deaktivieren Sie den Button, solange das Eingabefeld leer ist (
disabled={text.trim() === ""}) - auch das ist ein aus dem State abgeleiteter Wert.
Teil C - Echter und abgeleiteter Zustand
Abschnitt betitelt „Teil C - Echter und abgeleiteter Zustand“DicePair- zwei Würfel und ein “Würfeln”-Button. Schritte:- Zwei States für die beiden Augenzahlen (1 bis 6). Der Button setzt beide neu (
Math.floor(Math.random() * 6) + 1). - Bei einem Pasch (beide gleich) erscheint eine Meldung “Pasch!”. Diese Meldung ist kein eigener State, sondern wird beim Rendern aus den beiden Würfelwerten berechnet (
dieA === dieB). - Begründen Sie im Kommentar, welcher Fehler bei einem zusätzlichen
isDouble-State entstehen könnte (Stichwort: zwei Wahrheiten, die auseinanderlaufen, wenn man einmal vergisst, beide zu aktualisieren).
- Zwei States für die beiden Augenzahlen (1 bis 6). Der Button setzt beide neu (
- Erstellen Sie für alle vier Komponenten eine State-Tabelle (Variable, echter State oder abgeleitet, Begründung in Stichworten). Prüfkriterium für “echter State”: Er entsteht nur durch eine Benutzeraktion und lässt sich aus nichts anderem berechnen.
Teil D - Expertenteil: State heben
Abschnitt betitelt „Teil D - Expertenteil: State heben“Ausgangslage: Ihre vier Komponenten funktionieren, kennen einander aber nicht. Jetzt kommt eine Anforderung, die sie verbindet.
- Über allen vier Komponenten soll eine Leiste “Interaktionen gesamt: n” jede Aktion in jeder Komponente mitzählen. Entwerfen Sie zuerst auf Papier: Wo muss dieser Zähler leben, und warum kann er in keiner der vier Komponenten selbst wohnen? (Antwort in Stichworten notieren.)
- Implementieren Sie das Muster State heben: Der Zähler-State wandert in die Elternkomponente (
UebungPageoder eine neue Leisten-Komponente darüber). Jede der vier Komponenten bekommt eine Callback-ProponInteraction: () => voidund ruft sie bei jeder Aktion auf; kein Kind kennt den Zähler selbst. Das ist “Props runter, Events rauf” in Reinform. - Härtetest: Die Leiste soll zusätzlich anzeigen, welche Komponente zuletzt benutzt wurde. Erweitern Sie die Signatur zu
onInteraction(source: string)(jedes Kind meldet seinen Namen mit) und begründen Sie in zwei Sätzen, warum die Alternative - jedes Kind schreibt direkt in eine globale Variable - den Einweg-Datenfluss von React zerstören würde. - Beurteilen Sie in zwei Sätzen: Nach welcher Regel entscheiden Sie ab jetzt, auf welcher Ebene der Hierarchie ein State wohnen muss?
Wissenscheck
Abschnitt betitelt „Wissenscheck“- Woran erkennen Sie, dass ein Wert kein State sein sollte?
- Warum bewirkt
items.push(...)keine Aktualisierung der Anzeige? - Was ist der Vorteil der Setter-Funktionsform
setCount((c) => c + 1)? - Was bedeutet “Props runter, Events rauf” konkret in Teil D?
- Welche zwei Wahrheiten können bei einem redundanten
isDouble-State auseinanderlaufen?
Git-Repository mit der Übungsseite; die State-Tabelle aus Teil C in der README.