React'te Üst Bileşenin State'ini Alt Bileşende Değiştirme
Önceki derste, veri state'i üst bileşende saklanıyordu ve alt bileşenler bu verileri prop'lar olarak alıyordu.
Şimdi ürünlerimizi değiştirmek istediğimizi varsayalım.
Örneğin, ürünümüzü sepete atacak bir buton yapalım. Başlangıç olarak
ürünler dizimize, ürünün sepette olup olmadığını gösteren
bir inCart alanı ekleyelim:
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 bileşeninde, ürün etiketine
bir inCart özelliği daha ekleyelim:
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>;
}
Şimdi alt Product bileşeninde
sepet bilgisini gösteren çıktıyı ve sepete ekleme
butonunu yapalım:
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>;
}
Ekleme İşlemini Uygulayalım
React kurallarına göre bir bileşen kendi prop'larını değiştirmemelidir. Bu,
alt bileşenin inCart prop'unu değiştirerek kendisini sepete koyamayacağı anlamına gelir.
Bu doğru değildir.
Doğrusu, üst bileşenden, kendi prods state'ini değiştirerek
belirli bir ürünü sepete koymasını istemek olacaktır.
Bunun nasıl yapıldığına bir bakalım.
Üst bileşende, parametre olarak ürünün id'sini alan ve
bu ürün için inCart özelliğini true olarak değiştiren
bir addToCart fonksiyonu yapalım:
function addToCart(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.inCart = true;
}
return prod;
}));
}
Ürün etiketine, oluşturduğumuz fonksiyonu ileteceğimiz bir özellik ve ayrıca
ürünün id'sini ileteceğimiz bir özellik daha ekleyelim:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name ={prod.name}
cost ={prod.cost}
inCart ={prod.inCart}
addToCart={addToCart}
/>;
});
Gördüğünüz gibi, bileşenlerin prop'larına sadece veri değil, fonksiyonlar da iletebilirsiniz.
Products sınıfının son kodları şu şekilde olacaktır:
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>;
}
Şimdi alt sınıfta addToCart fonksiyonu erişilebilir olacak.
Butona tıklandığında, ürünün id'sini parametre olarak ileterek bu fonksiyonu çağıralım:
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>;
}
Sonuç olarak, alt bileşendeki butona tıklandığında, üst bileşenin state'ini değiştirecek olan üst bileşenin fonksiyonu tetiklenecektir. Üst bileşenin state'indeki değişiklik, yeniden oluşturma (re-render) tetikleyecek ve ürünümüzü, değiştirilmiş prop'u ileterek yeniden çizecektir.
Önceki dersteki User bileşenini alın.
Kullanıcıyı yasaklamak (ban) için bir buton ekleyin.