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:
jsxconst 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:
jsxfunction 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į:
jsxfunction 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:
jsxfunction 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:
jsxconst 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:
jsxfunction 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:
jsxfunction 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.