React'ta Üst Bileşenin State'ini Alt Bileşende Düzenleme

Şimdi ürünlerimizi input'lar kullanarak düzenleyelim. Bunun için alt bileşende bir buton yapalım.

Bu butona ilk tıklandığında, ürünün adı ve fiyatı yerine bunları düzenlemek için input'lar görünsün, ikinci tıklamada ise input'lar yerine tekrar metinler görünsün.

Ürünler dizisinde, isEdit özelliğini ekleyerek bir değişiklik yapalım (ve basitlik için sepet işlevini kaldıralım):

jsxconst initProds = [
  {id: id(), name: 'product1', cost: 100, isEdit: false},
  {id: id(), name: 'product2', cost: 200, isEdit: false},
  {id: id(), name: 'product3', cost: 300, isEdit: false},
];

Product Bileşeni

Ürün için düzenleme butonu yapalım:

jsxfunction Product({ id, name, cost, isEdit }) {
  return <div>
    name: <span>{name}</span>
    cost: <span>{cost}</span>
    <button>edit</button>
  </div>;
}

Bu butona tıklandığında, üst bileşenden iletilen toggleMode adlı bir fonksiyonun çağrılmasını sağlayalım:

jsxfunction Product({ id, name, cost, isEdit, toggleMode }) {
  return <div>
    name: <span>{name}</span>
    cost: <span>{cost}</span>
    
    <button onClick={() => toggleMode(id)}>
      edit
    </button>
  </div>;
}

Henüz toggleMode uygulamamız yok, ancak onun üst bileşende bulunacağını, bir parametre olarak ürünün id' sini alacağını ve ürünün isEdit özelliğini tersine çevireceğini biliyoruz.

Ayrıca, butonun metninin her tıklamada değişmesini sağlayalım:

jsxfunction Product({ id, name, cost, isEdit, toggleMode }) {
  return <div>
    name: <span>{name}</span>
    cost: <span>{cost}</span>
    
    <button onClick={() => toggleMode(id)}>
      {isEdit ? 'save': 'edit'}
    </button>
  </div>;
}

Şimdi, düzenleme modunda input'ların ve normal modda span'ların görünmesini sağlayalım:

jsxfunction Product({ id, name, cost, isEdit, toggleMode }) {
  return <div>
    name: {isEdit ? <input value={name} /> : <span>{name}</span>}
    cost: {isEdit ? <input value={cost} /> : <span>{cost}</span>}
    
    <button onClick={() => toggleMode(id)}>
      {isEdit ? 'save': 'edit'}
    </button>
  </div>;
}

Input'larımıza, içinde bir üst bileşen fonksiyonu olan editProd'yu çağıracağımız bir onChange olayı bağlayalım:

jsxfunction Product({ id, name, cost, isEdit, toggleMode, editProd }) {
  return <div>
    name: {
      isEdit
      ? <input value={name} onChange={event => editProd(id, 'name', event)} />
      : <span>{ name }</span>
    }
    cost: {
      isEdit
      ? <input value={cost} onChange={event => editProd(id, 'cost', event)} />
      : <span>{ cost }</span>
    }
    
    <button onClick={() => toggleMode(id)}>
      {isEdit ? 'save': 'edit'}
    </button>
  </div>;
}

Products Bileşeni

Şimdi Products bileşenine geçelim. İçinde toggleMode fonksiyonunu uygulayalım:

jsxfunction toggleMode(id) {
  setProds(prods.map(prod => {
    if (prod.id === id) {
      prod.isEdit = !prod.isEdit;
    }
    
    return prod;
  }));
}

Ayrıca içinde editProd fonksiyonunu uygulayalım:

jsxfunction editProd(id, field, event) {
  setProds(prods.map(prod => {
    if (prod.id === id) {
      prod[field] = event.target.value;
    }
    
    return prod;
  }));
}

Ürün etiketine, toggleMode ve editProd fonksiyonlarımızı özellik olarak iletilim:

jsxconst items = prods.map(prod => {
  return <Product
    key ={prod.id}
    id  ={prod.id}
    name={prod.name}
    cost={prod.cost}
    isEdit={prod.isEdit}
    toggleMode={toggleMode}
    editProd={editProd}
  />;
});

Products bileşeninin son kodu şu şekilde olacaktır:

jsxfunction Products() {
  const [prods, setProds] = useState(initProds);
  
  function toggleMode(id) {
    setProds(prods.map(prod => {
      if (prod.id === id) {
        prod.isEdit = !prod.isEdit;
      }
      
      return prod;
    }));
  }
  
  function editProd(id, field, event) {
    setProds(prods.map(prod => {
      if (prod.id === id) {
        prod[field] = event.target.value;
      }
      
      return prod;
    }));
  }
  
  const result = prods.map(prod => {
    return <Product
      key ={prod.id}
      id  ={prod.id}
      name={prod.name}
      cost={prod.cost}
      isEdit={prod.isEdit}
      toggleMode={toggleMode}
      editProd={editProd}
    />;
  });
  
  return <div>
    {result}
  </div>;
}

Pratik Görevler

Задание 1

Önceki derslerde oluşturduğunuz Users ve User bileşenleriyle benzer işlemleri gerçekleştirin.