Promena stanja roditelja u podređenoj komponenti u React-u
U prethodnoj lekciji naše stanje sa podacima je čuvano u roditeljskoj komponenti, a podređene komponente su dobijale te podatke u vidu prosledjenih vrednosti (props).
Recimo sada da želimo da menjamo naše proizvode.
Hajde da napravimo, na primer, dugme koje će
dodavati naš proizvod u korpu. Za početak
hajde da dodamo u naš niz sa proizvodima
polje inCart koje pokazuje da li je
proizvod u korpi ili 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},
];
U komponenti Products u tag za proizvod
dodajmo još jedan 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>;
}
Hajde da u podređenoj komponenti Product
realizujemo prikaz informacije o korpi i dugme
za dodavanje u korpu:
function Product({ id, name, cost, inCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'u korpi' : 'nije u korpi'}</span>
<button>u korpu</button>
</div>;
}
Realizujmo dodavanje
Prema pravilima React-a, komponenta ne treba
da menja svoje prosledjene vrednosti (props). To znači da
podređena komponenta ne može sama sebe
dodati u korpu, menjajući prosledjenu vrednost inCart.
To nije ispravno.
Ispravno je zamoliti roditeljsku komponentu
da promeni svoje stanje prods, dodajući
određeni proizvod u korpu.
Hajde da vidimo kako se to radi.
U komponenti-roditelju napravimo funkciju addToCart,
koja kao parametar prihvata id proizvoda
i za taj proizvod menja svojstvo inCart
na true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
U tag za proizvod dodajmo atribut, u koji
prosledimo našu kreiranu funkciju, kao i
atribut, u koji prosledimo id proizvoda:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Kao što vidite, u prosledjene vrednosti komponenti možete proslediti ne samo neke podatke, već i funkcije.
Završni kod komponente Products će biti
sledeći:
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>;
}
Sada će u podređenoj komponenti biti dostupna
funkcija addToCart. Pozovimo ovu funkciju
klikom na dugme, prosledivši joj kao parametar
id proizvoda:
function Product({ id, name, cost, inCart, addToCart }) {
return <div>
name: <span>{name}</span>,
cost: <span>{cost}</span>,
<span>{inCart ? 'u korpi' : 'nije u korpi'}</span>
<button onClick={() => addToCart(id)}>u korpu</button>
</div>;
}
Ispostavlja se da će klikom na dugme u potomku biti pozvana funkcija roditelja, koja će i promeniti stanje roditelja. Promena roditeljskog stanja će pokrenuti ponovno renderovanje i ponovo će nacrtati naš proizvod, prosledivši mu izmenjenu prosledjenu vrednost.
Uzmite komponentu User iz prethodne
lekcije. Uredite je tako da se u njoj pojavi
dugme za banovanje korisnika.