Режими на работа преку состојби на компоненти-потомци во React

Нека нашиот производен низа сега изгледа на следниов начин:

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

Ајде да ги прикажеме овие производи во форма на HTML табела. Истовремено, ќе направиме така што при кликнување на која било ќелија од табелата во таа ќелија да се појави влезно поле за уредување. За да ја решите задачата ќе направиме 3 компоненти.

Компонентата Products ќе ја чува состојбата со производите и ќе ги користи компонентите Product за приказ на производите. Компонентата Product пак ќе ги користи компонентите ProductField за приказ на одредено поле на производот (име, цена, категорија).

Компонентата ProductField или ќе го прикажува текстот на полето, или влезно поле за негово уредување. Притоа, режимот на уредување или приказ нека се регулира со состојбата на оваа компонента.

Односно, ние нема да го чуваме режимот во родителската состојба. Таму тоа би било многу незгодно, бидејќи ќе треба да го наведеме режимот за секое поле на производот, што би ја претворило нашата состојба во нешто слично на ова:

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

Ние, сепак, нема да направиме ваква состојба, туку ќе ја оставиме онаа што беше. Едноставно, секоја инстанца на компонентата ProductField со помош на својата состојба ќе го регулира режимот: или уредување, или приказ.

На овој начин ќе испадне дека родителската компонента ќе ја чува состојбата со податоците, а нашата компонента-внук ќе ги добива овие податоци преку пропси и притоа ќе има своја состојба за промена на својот режим.

Значи, ајде да го имплементираме опишаното.

Компонента 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>;
}

Компонента 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>;
}

Компонента 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>;
}

Практични задачи

Задание 1

Извршете ги сличните операции со компонентите Users и User, создадени од вас во претходните лекции.