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 компоненттерімен де осындай операцияларды орындаңыз.