State nach oben heben
Die Festival-App besteht jetzt aus Komponenten: einer Kopfzeile oben und einer BandKarte für jede Band. Jede Karte hat einen Stern-Button und merkt sich in ihrem eigenen State, ob ihre Band ein Favorit ist, wie du es in der State-Lektion gesehen hast. Jetzt soll die Kopfzeile sagen, wie viele Favoriten es gibt. Aber das geht nicht: Der State steckt in den Karten, und eine Komponente kann den State einer anderen nicht lesen. Props gehen nur in eine Richtung, von einem Parent nach unten zu seinen Kindern.
Wenn zwei Komponenten denselben State brauchen, verschiebst du ihn nach oben, in ihren nächsten gemeinsamen Parent: die nächste Komponente, in der beide stecken. Hier ist das App. Dort lebt der State, und App gibt jedem Kind als Props, was es braucht: den Wert und eine Funktion, die ihn ändert. Das nennt man State nach oben heben (lifting state up).
Ein kleines Beispiel mit zwei Komponenten in einer Datei: Der Warenkorb zeigt die Tickets, die du gekauft hast, und ein Button darunter kauft ein weiteres:
import { useState } from "react";
export default function App() {
const [tickets, setTickets] = useState(0);
function kaufen() {
setTickets((tickets) => tickets + 1);
}
return (
<main>
<Warenkorb tickets={tickets} />
<KaufButton beiKauf={kaufen} />
</main>
);
}
function Warenkorb({ tickets }) {
return <p>Tickets in deinem Warenkorb: {tickets}</p>;
}
function KaufButton({ beiKauf }) {
return <button onClick={beiKauf}>Ticket kaufen</button>;
}KaufButton weiß nicht, was Kaufen bewirkt. Er ruft nur beiKauf auf, wenn er angeklickt wird. App entscheidet, was passiert, ändert seinen State und rendert neu, sodass Warenkorb die neue Zahl in seinen Props bekommt. Der State liegt an einer Stelle, und beide Kinder verwenden denselben Wert.
Bei den Favoriten hält App ein Array mit den IDs der Favoriten-Bands. Jede Karte bekommt zwei Props: favorit, ob ihre Band im Array steht, und beiFavoritUmschalten, eine Funktion, die die Band ins Array aufnimmt oder herausnimmt:
function favoritUmschalten(id) {
if (favoriten.includes(id)) {
setFavoriten((favoriten) =>
favoriten.filter((favoritId) => favoritId !== id),
);
} else {
setFavoriten((favoriten) => [...favoriten, id]);
}
}beiFavoritUmschalten={() => favoritUmschalten(band.id)} gibt jeder Karte eine Funktion, die ihre Band schon kennt, wie in der Ereignisse-Lektion. Und die Karte braucht kein useState mehr: Sie zeigt, was ihre Props sagen, und ruft beiFavoritUmschalten auf, wenn ihr Stern angeklickt wird.
So schreibst du es:
Anweisungen
- 1
Halte in
Appdie Favoriten in einer State-Variablenfavoriten: einem Array von IDs, das leer beginnt. Gib jederBandKartedie PropsfavoritundbeiFavoritUmschaltenund verwende sie inBandKarte.jsxstatt des eigenen States der Karte. - 2
Gib
Kopfzeiledie Zahl der Favoriten alsanzahl. Markiere ein paar Bands mit einem Stern, um es auszuprobieren.