Změna stavu rodiče v dětské komponentě v Reactu
V předchozí lekci jsme měli stav s daty uložený v rodičovské komponentě a dětské komponenty tato data získávaly jako props.
Nyní předpokládejme, že chceme naše produkty měnit.
Vytvořme například tlačítko, které bude
přidávat náš produkt do košíku. Pro začátek
přidejme do našeho pole s produkty
pole inCart, které ukazuje, zda je produkt
v košíku nebo ne:
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},
];
V komponentě Products přidejme do tagu s produktem
ještě jeden atribut inCart:
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>;
}
V dětské komponentě Product
udělejme výpis informace o košíku a tlačítko
pro přidání do košíku:
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>;
}
Implementujeme přidání
Podle pravidel Reactu komponenta by neměla
měnit své props. To znamená, že
dětská komponenta nemůže sama sebe
přidat do košíku změnou props inCart.
To není správně.
Správně je požádat rodičovskou komponentu,
aby změnila svůj stav prods a přidala
daný produkt do košíku.
Podívejme se, jak se to dělá.
V komponentě-rodiči vytvořme funkci addToCart,
která parametrem přijímá id produktu
a pro tento produkt mění vlastnost inCart
na true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Do tagu s produktem přidejme atribut, do kterého
předáme naši vytvořenou funkci, a také
atribut, do kterého předáme id produktu:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Jak vidíte, do props komponent lze předávat nejen nějaká data, ale i funkce.
Výsledný kód třídy Products bude
vypadat následovně:
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>;
}
Nyní bude v dětské třídě dostupná
funkce addToCart. Zavolejme tuto funkci
po kliknutí na tlačítko a předejme jí parametrem
id produktu:
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>;
}
Stane se, že po kliknutí na tlačítko v potomkovi se zavolá funkce rodiče, která změní stav rodiče. Změna stavu rodiče způsobí překreslení a překreslí náš produkt a předá mu změněný props.
Vezměte komponentu User z předchozí
lekce. Udělejte to, aby se v něm objevilo
tlačítko pro zabanování uživatele.