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 таблицасы түрүндө чыгаралы. Ошону менен бирге, таблицанын каалаган уячасына басканда, ошол уячада оңдоо үчүн input пайда болсун. Маселени чыгаруу үчүн биз 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 компоненттери менен ушул сыяктуу амалдарды аткарыңыз.