Reactda ota komponentning holatini bola komponentda tahrirlash

Keling, endi mahsulotlarimizni inputlar orqali tahrirlaymiz. Buning uchun bola komponentda tugma yaratamiz.

Ushbu tugmani birinchi bosilganda, mahsulot nomi va narxi o'rniga ularni tahrirlash uchun inputlar paydo bo'lsin, ikkinchi bosilganda esa inputlar o'rniga yana matnlar paydo bo'lsin.

Mahsulotlar massiviga o'zgartirish kiritamiz, isEdit xususiyatini qo'shamiz (soddalik uchun savat bilan ishlashni olib tashlaymiz):

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 komponenti

Mahsulotda tahrirlash uchun tugma yaratamiz:

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

Keling, ushbu tugma bosilganda ota komponentdan o'tkazilgan toggleMode funktsiyasi chaqirilsin:

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

Hozirda bizda toggleMode ning amalga oshirilishi yo'q, lekin biz bilamizki, u ota komponentda joylashgan bo'ladi, parametr sifatida mahsulotning id sini qabul qiladi va mahsulotning isEdit xususiyatini teskari holatga o'zgartiradi.

Shuningdek, tugma matni har bir bosilganda o'zgarishini ta'minlaymiz:

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>;
}

Keling, endi tahrirlash rejimida ma'lumotlar bilan inputlar paydo bo'lishini, oddiy rejimda esa span lar paydo bo'lishini ta'minlaymiz:

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>;
}

Inputlarimizga onChange hodisasini bog'laymiz, unda ota komponentning editProd funktsiyasini chaqiramiz:

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 komponenti

Keling, endi Products komponentiga o'tamiz. Undagi toggleMode funktsiyasini amalga oshiramiz:

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

Shuningdek, undagi editProd funktsiyasini amalga oshiramiz:

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

Mahsulot tegi atributlari orqali bizning toggleMode va editProd funktsiyalarimizni o'tkazamiz:

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 komponentining yakuniy kodi quyidagicha bo'ladi:

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>;
}

Amaliy vazifalar

Задание 1

Oldingi darslarda yaratgan Users va User komponentlari bilan shunga o'xshash amallarni bajaring.