Mode Kerja melalui State Komponen Anak di React

Misalkan array produk kita sekarang terlihat seperti berikut:

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'},
];

Mari kita tampilkan produk-produk ini dalam bentuk tabel HTML. Sekaligus kita buat agar ketika sel tabel mana pun diklik, muncul input untuk mengedit di sel tersebut. Untuk menyelesaikan tugas ini, kita akan membuat 3 komponen.

Komponen Products akan menyimpan state produk dan menggunakan komponen Product untuk menampilkan produk. Komponen Product pada gilirannya juga akan menggunakan komponen ProductField untuk menampilkan field tertentu produk (nama, harga, kategori).

Komponen ProductField akan menampilkan teks field, atau input untuk mengeditnya. Mode edit atau tampil ini biarkan diatur oleh state komponen ini sendiri.

Artinya, kita tidak akan menyimpan mode di state induk. Di sana akan sangat tidak nyaman, karena kita harus menentukan mode untuk setiap field produk, yang akan mengubah state kita menjadi seperti ini:

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},
  ],
]

Namun, kita tidak akan membuat state seperti itu, tetapi membiarkan state yang sebelumnya. Setiap instance komponen ProductField dengan menggunakan state-nya sendiri akan mengatur mode: baik edit maupun tampil.

Dengan demikian, komponen induk akan menyimpan state dengan data, dan komponen cucu kita akan menerima data ini melalui props dan sekaligus memiliki state sendiri untuk mengubah modenya.

Jadi, mari kita implementasikan yang telah dijelaskan.

Komponen Products

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

Komponen Product

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

Komponen ProductField

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

Tugas Praktis

Задание 1

Lakukan operasi serupa dengan komponen Users dan User, yang telah Anda buat dalam pelajaran sebelumnya.