Ändern des Parent-State in einer Child-Komponente in React
In der vorherigen Lektion wurde der State mit den Daten in der Parent-Komponente gespeichert, und die Child- Komponenten erhielten diese Daten als Props.
Nehmen wir nun an, wir möchten unsere Produkte ändern.
Wir erstellen beispielsweise einen Button, der
unser Produkt in den Warenkorb legt. Fügen wir zunächst
unserem Produkt-Array ein Feld inCart hinzu,
das anzeigt, ob sich das Produkt im Warenkorb befindet
oder nicht:
const initProds = [
{id: id(), name: 'product1', cost: 100, inCart: false},
{id: id(), name: 'product2', cost: 200, inCart: false},
{id: id(), name: 'product3', cost: 300, inCart: false},
];
In der Komponente Products fügen wir dem
Produkt-Tag ein weiteres Attribut inCart hinzu:
function Products() {
const [prods, setProds] = useState(initProds);
const items = prods.map(prod => {
return <Product
key ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart={prod.inCart}
/>;
});
return <div>
{items}
</div>;
}
Erstellen wir nun in der Child-Komponente Product
eine Ausgabe der Warenkorb-Information und einen Button
zum Hinzufügen zum Warenkorb:
function Product({ id, name, cost, inCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'in cart' : 'not in cart'}</span>
<button>to cart</button>
</div>;
}
Implementieren des Hinzufügens
Laut React-Regeln sollte eine Komponente nicht
ihre eigenen Props ändern. Das bedeutet, dass
die Child-Komponente sich nicht selbst in den
Warenkorb legen kann, indem sie das Prop inCart
ändert. Das ist nicht korrekt.
Korrekt wäre, die Parent-Komponente zu bitten,
ihren State prods zu ändern und ein
bestimmtes Produkt in den Warenkorb zu legen.
Sehen wir uns an, wie das gemacht wird.
Erstellen wir in der Parent-Komponente eine Funktion addToCart,
die die id des Produkts als Parameter entgegennimmt
und für dieses Produkt die Eigenschaft inCart
auf true setzt:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Dem Produkt-Tag fügen wir ein Attribut hinzu, in dem
wir die von uns erstellte Funktion übergeben, sowie
ein weiteres Attribut, in dem wir die id des Produkts übergeben:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Wie Sie sehen, können an Komponenten-Props nicht nur Daten, sondern auch Funktionen übergeben werden.
Der endgültige Code der Products-Komponente
wird wie folgt aussehen:
function Products() {
const [prods, setProds] = useState(initProds);
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
return <div>
{items}
</div>;
}
Nun ist in der Child-Komponente die Funktion
addToCart verfügbar. Rufen wir diese Funktion
beim Klick auf den Button auf und übergeben ihr
die id des Produkts als Parameter:
function Product({ id, name, cost, inCart, addToCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'in cart' : 'not in cart'}</span>
<button onClick={() => addToCart(id)}>to cart</button>
</div>;
}
Das Ergebnis ist, dass beim Klick auf den Button im Child die Funktion des Parents aufgerufen wird, die dann den Parent-State ändert. Die Änderung des Parent-State wird ein Re-Rendering auslösen und unser Produkt neu zeichnen, wobei ihm der geänderte Prop übergeben wird.
Nehmen Sie die User-Komponente aus der vorherigen
Lektion. Sorgen Sie dafür, dass darin ein Button
zum Bannen eines Users erscheint.