Reactда ота-компонентнинг стейтини фарзанд-компонентда ўзгартириш
Олдинги дарсда бизда маълумотлар стейти ота-компонентда сақланар эди, фарзанд-компонентлар эса ушбу маълумотларни пропслар сифатида олар эдилар.
Энди биз махсулотларимизни ўзгартиришни истаймиз.
Масалан, бизнинг махсулотимизни саватга қўйадиган
тугма ясайлик. Аввал бизнинг махсулотлар массивимизга
махсулот саватда бор-йўқлигини кўрсатадиган inCart
майдонини қўшайлик:
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 компонентида махсулот билан тегга
яна бир 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>;
}
Келинг фарзанд Product компонентида
сават ҳақида маълумот чиқариш ва саватга қўшиш
учун тугма ясайлик:
function Product({ id, name, cost, inCart }) {
return <div>
номи: <span>{name}</span>,
нархи: <span>{cost}</span>,
<span>{inCart ? 'саватда' : 'саватда эмас'}</span>
<button>саватга</button>
</div>;
}
Қўшишни амалга оширамиз
React қоидаларига кўра компонент ўз пропсларини
ўзгартирмаслиги керак. Бу демакки, фарзанд компонент
ўзини ўзи саватга қўйолмайди, inCart пропсини
ўзгартириб. Бу нотўғри.
Тўғриси, ота-компонентдан ўз стейти prods ни
ўзгартириб, белгиланган махсулотни саватга қўйишни
сўраш бўлади.
Келинг бу қандай бажарилишини кўрамиз.
Ота-компонентда addToCart функциясини ясаймиз,
у параметр сифатида махсулотнинг id сини қабул қилади
ва ушбу махсулот учун inCart хосисасини
true га ўзгартиради:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Махсулот билан тегга биз яратилган функцияни ўтказадиган
атрибутни, шунингдек, махсулотнинг 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}
/>;
});
Кўриб турганingizдек, компонентларнинг пропсларига фақатгина маълумотлар эмас, балки функцияларни ҳам ўтказish мумкин.
Products синфининг якуний коди куйидагича бўлади:
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>;
}
Энди фарзанд синфида бизга addToCart функцияси мавжуд бўлади.
Ушбу функцияни тугма босишда чақирамиз, унга параметр сифатида
махсулотнинг id сини ўтказамиз:
function Product({ id, name, cost, inCart, addToCart }) {
return <div>
номи: <span>{name}</span>,
нархи: <span>{cost}</span>,
<span>{inCart ? 'саватда' : 'саватда эмас'}</span>
<button onClick={() => addToCart(id)}>саватга</button>
</div>;
}
Натижада, фарзанддаги тугма босилганда отанинг функцияси ишга тушади, ва у отанинг стейтини ўзгартиради. Отанинг стейтининг ўзгариши қайта рендерни чақиради ва бизнинг махсулотимизни ўзгартирилган пропс ўтказиб, қайта чизади.
Олдинги дарсдан User компонентини олинг.
Унда фойдаланувчини бан қилиш учун тугма ясанг.