Spreminjanje stanja starša v podrejenem komponentu v React
V prejšnji lekciji je bilo stanje s podatki shranjeno v nadrejenem komponentu, podrejeni komponenti pa so te podatke prejemali v obliki propov.
Recimo, da zdaj želimo spreminjati naše produkte.
Naredimo na primer gumb, ki bo
dodal naš produkt v košarico. Za začetek
dodajmo v naš array s produkti
polje inCart, ki prikazuje, ali je produkt
v košarici ali 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 komponento Products v tag z izdelkom
dodajmo še en 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 podrejenem komponentu Product
naredimo izpis informacije o košarici in gumb
za dodajanje v košarico:
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>;
}
Implementirajmo dodajanje
Po pravilih React komponenta ne sme
spreminjati svojih propov. To pomeni, da
podrejeni komponent ne more sam sebe
dati v košarico s spreminjanjem propa inCart.
To ni pravilno.
Pravilno je, da prosimo nadrejeni komponent,
da spremeni svoje stanje prods in določen
izdelek doda v košarico.
Poglejmo, kako se to naredi.
V komponenti-staršu naredimo funkcijo addToCart,
ki kot parameter sprejme id izdelka
in za ta izdelek spremeni lastnost inCart
v true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
V tag z izdelkom dodajmo atribut, v katerega
posredujemo ustvarjeno funkcijo, in
atribut, v katerega posredujemo id izdelka:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Kot lahko vidite, lahko v prope komponent posredujete ne le nekaj podatkov, ampak tudi funkcije.
Končna koda razreda Products bo
naslednja:
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>;
}
Zdaj bo v podrejenem razredu na voljo
funkcija addToCart. Pokličimo to funkcijo
ob kliku na gumb in ji posredujmo kot parameter
id izdelka:
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>;
}
Izkazalo se bo, da bo ob kliku na gumb v potomcu poklicala funkcija starša, ki bo spremenila stanje starša. Spreminjanje stanja starša bo povzročilo ponovno upodabljanje in ponovno risanje našega izdelka, pri čemer mu bo posredoval spremenjen prop.
Vzemite komponento User iz prejšnje
lekcije. Naredite tako, da se v njej pojavi
gumb za ban uporabnika.