Tėvinio komponento būsenos keitimas vaikiniame komponente React
Ankstesnėje pamokoje mūsų duomenų būsena buvo saugoma tėviniame komponente, o vaikiniai komponentai gaudavo šiuos duomenis kaip props.
Tarkime, dabar norime keisti savo produktus.
Sukurkime, pavyzdžiui, mygtuką, kuris
įdės mūsų produktą į krepšelį. Pirmiausia
į mūsų produktų masyvą pridėkime
lauką inCart, rodantį, ar produktas
yra krepšelyje, ar 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},
];
Products komponente į produkto žymą
pridėkime dar vieną 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>;
}
Vaikiniame komponente Product
sukurkime informacijos apie krepšelį išvedimą ir mygtuką
pridėjimui į krepšelį:
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>;
}
Įgyvendinkime pridėjimą
Pagal React taisykles komponentas neturėtų
keisti savo props. Tai reiškia, kad
vaikinis komponentas negali pats save
įdėti į krepšelį, pakeisdamas props inCart.
Tai neteisinga.
Teisinga būtų paprašyti tėvinio komponento
pakeisti savo būseną prods, įdėjus
tam tikrą produktą į krepšelį.
Pažiūrėkime, kaip tai daroma.
Tėviniame komponente sukurkime funkciją addToCart,
kuri parametru priima id produkto
ir šiam produktui keičia savybę inCart
į true:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Į produkto žymą pridėkime atributą, į kurį
perduosime mūsų sukurtą funkciją, taip pat
atributą, į kurį perduosime produkto id:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Kaip matote, į komponentų props galima perduoti ne tik kokius nors duomenis, bet ir funkcijas.
Galutinis Products klasės kodas bus
toks:
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>;
}
Dabar vaikinėje klasėje mums bus prieinama
funkcija addToCart. Iškvieskime šią funkciją
paspaudus mygtuką, perduodant jai parametru
produkto id:
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>;
}
Pasirodo, kad paspaudus mygtuką vaikiniame komponente būs iškviesta tėvinio komponento funkcija, kuri ir pakeis tėvinio komponento būseną. Tėvinio komponento būsenos pakeitimas sukels perrenderinimą ir perbraižys mūsų produktą, perduodant jam pakeistą props.
Paimkite komponentą User iš ankstesnės
pamokos. Padarykite taip, kad jame atsirastų
mygtukas vartotojo užblokavimui.