Reactda avlod komponentlari holatlari orqali ishlash rejimlari

Endi bizning mahsulotlar massivimiz quyidagicha ko'rinishga ega bo'lsin:

jsxconst initProds = [
  {id: id(), name: 'prod1', cost: 'cost1', catg: 'catg1'},
  {id: id(), name: 'prod2', cost: 'cost2', catg: 'catg2'},
  {id: id(), name: 'prod3', cost: 'cost3', catg: 'catg3'},
];

Keling, ushbu mahsulotlarni HTML jadvali shaklida chiqaramiz. Shu bilan birga, jadvalning har qanday katagiga bosilganda, o'zgartirish uchun input paydo bo'lishini ta'minlaymiz. Masalani hal qilish uchun 3 ta komponent yaratamiz.

Products komponenti mahsulotlar bilan holatni saqlaydi va mahsulotlarni chiqarish uchun Product komponentlaridan foydalanadi. Product komponenti o'z navbatida ma'lum bir mahsulot maydonini (nomi, narxi, toifasi) chiqarish uchun ProductField komponentlaridan foydalanadi.

ProductField komponenti maydon matnini ham, uning o'zgartirilishi uchun inputni ham ko'rsatadi. Bunda tahrirlash yoki ko'rsatish rejimi ushbu komponentning holati bilan boshqarilsin.

Ya'ni biz rejimni ota komponent holatida saqlamaymiz. Bu juda noqulay bo'lar edi, chunki har bir mahsulot maydoni uchun rejimni ko'rsatishimiz kerak bo'lar edi, bu esa bizning holatimizni quyidagiga o'xshash narsaga aylantirardi:

jsxconst initProds = [
  [
    {field: 'name', value: 'prod1', isEdit: false},
    {field: 'cost', value: 'cost1', isEdit: false},
    {field: 'catg', value: 'catg1', isEdit: false},
  ],
  [
    {field: 'name', value: 'prod2', isEdit: false},
    {field: 'cost', value: 'cost2', isEdit: false},
    {field: 'catg', value: 'catg2', isEdit: false},
  ],
  [
    {field: 'name', value: 'prod3', isEdit: false},
    {field: 'cost', value: 'cost3', isEdit: false},
    {field: 'catg', value: 'catg3', isEdit: false},
  ],
]

Biroq, biz bunday holat yaratmaymiz, balki avvalgisi bo'lganini qoldiramiz. Shunchaki, har bir ProductField komponenti namunasi o'z holati yordamida rejimni boshqaradi: tahrirlash yoki ko'rsatish.

Shunday qilib, ota komponent ma'lumotlar bilan holatni saqlaydi, bizning nevaralar komponenti esa ushbu ma'lumotlarni prop orqali oladi va shu bilan birga o'z rejimini o'zgartirish uchun o'z holatiga ega bo'ladi.

Shunday qilib, keling tavsiflangan narsani amalga oshiramiz.

Products komponenti

jsxfunction Products() {
  const [prods, setProds] = useState(initProds);
  
  function changeField(id, field, event) {
    setProds(prods.map(prod => {
      if (prod.id === id) {
        prod[field] = event.target.value;
      }
      
      return prod;
    }));
  }
  
  const rows = prods.map(prod => {
    return <Product
      key ={prod.id}
      id  ={prod.id}
      name={prod.name}
      cost={prod.cost}
      catg={prod.catg}
      changeField={changeField}
    />;
  });
  
  return <div>
    <table>
      <tbody>
        {rows}
      </tbody>
    </table>
  </div>;
}

Product komponenti

jsxfunction Product({ id, name, cost, catg, changeField }) {
  return <tr>
    <ProductField id={id} text={name} type="name" changeField={changeField} />
    <ProductField id={id} text={cost} type="cost" changeField={changeField} />
    <ProductField id={id} text={catg} type="catg" changeField={changeField} />
  </tr>;
}

ProductField komponenti

jsxfunction ProductField({ id, text, type, changeField }) {
  const [isEdit, setIsEdit] = useState(false);
  
  return <td>
    {
      isEdit
      ? <input
        value={text}
        onChange={event => changeField(id, type, event)}
        onBlur={() => setIsEdit(false)}
      />
      : <span onClick={() => setIsEdit(true)}>{text}</span>
    }
  </td>;
}

Amaliy vazifalar

Задание 1

Users va User komponentlari bilan oldingi darslarda yaratganingizga o'xshash amallarni bajaring.