React'те бала компонентте ата-энесинин стейтин өзгөртүү

Келгиле, азыр биз өнүмдөрүбүздү инпуттар аркылуу өзгөртөлү. Бул үчүн бала компонентте баскыч жасайлы.

Бул баскычты биринчи жолу басканда, атынын жана баасынын ордуна, аларды өзгөртүү үчүн инпуттар пайда болсун, экинчи жолу басканда инпуттардын ордуна кайрадан тексттер пайда болсун.

Өнүмдөр массивине өзгөртүү киргизели, isEdit касиетин кошуп (ал эми себет менен иштөөнү жөнөкөйлөтүү үчүн алып салалы):

jsxconst initProds = [
  {id: id(), name: 'product1', cost: 100, isEdit: false},
  {id: id(), name: 'product2', cost: 200, isEdit: false},
  {id: id(), name: 'product3', cost: 300, isEdit: false},
];

Product Компоненти

Өнүмгө өзгөртүү үчүн баскыч жасайлы:

jsxfunction Product({ id, name, cost, isEdit }) {
  return <div>
    аты: <span>{name}</span>
    баасы: <span>{cost}</span>
    <button>өзгөртүү</button>
  </div>;
}

Бул баскычты чыкылдатканда, ата-эне компонентинен берилген toggleMode деген функция чакырылсын:

jsxfunction Product({ id, name, cost, isEdit, toggleMode }) {
  return <div>
    аты: <span>{name}</span>
    баасы: <span>{cost}</span>
    
    <button onClick={() => toggleMode(id)}>
      өзгөртүү
    </button>
  </div>;
}

Бизде азыр toggleMode функциясынын ишке ашырылышы жок, бирок биз анын ата-эне компоненттинде жайгашканын билебиз, ал параметр катары id өнүмүн кабыл алат жана isEdit касиетин өнүмдүн карама-каршысына өзгөртөт.

Ошондой эле баскычтын тексти ар бир чыкылдатууда өзгөрүшүн жасайлы:

jsxfunction Product({ id, name, cost, isEdit, toggleMode }) {
  return <div>
    аты: <span>{name}</span>
    баасы: <span>{cost}</span>
    
    <button onClick={() => toggleMode(id)}>
      {isEdit ? 'сактоо': 'өзгөртүү'}
    </button>
  </div>;
}

Келгиле, азыр өзгөртүү режиминде бизге маалыматтары бар инпуттар болсун, ал эми кадимки режимде - спандар болсун:

jsxfunction Product({ id, name, cost, isEdit, toggleMode }) {
  return <div>
    аты: {isEdit ? <input value={name} /> : <span>{name}</span>}
    баасы: {isEdit ? <input value={cost} /> : <span>{cost}</span>}
    
    <button onClick={() => toggleMode(id)}>
      {isEdit ? 'сактоо': 'өзгөртүү'}
    </button>
  </div>;
}

Инпуттарыбызга onChange окуясын байлап коёлу, анда биз кандайдыр бир ата-энелик editProd функциясын чакырабыз:

jsxfunction Product({ id, name, cost, isEdit, toggleMode, editProd }) {
  return <div>
    аты: {
      isEdit
      ? <input value={name} onChange={event => editProd(id, 'name', event)} />
      : <span>{ name }</span>
    }
    баасы: {
      isEdit
      ? <input value={cost} onChange={event => editProd(id, 'cost', event)} />
      : <span>{ cost }</span>
    }
    
    <button onClick={() => toggleMode(id)}>
      {isEdit ? 'сактоо': 'өзгөртүү'}
    </button>
  </div>;
}

Products Компоненти

Келгиле, азыр Products компонентине өтөлү. Анда toggleMode функциясын ишке ашыралы:

jsxfunction toggleMode(id) {
  setProds(prods.map(prod => {
    if (prod.id === id) {
      prod.isEdit = !prod.isEdit;
    }
    
    return prod;
  }));
}

Ошондой эле анда editProd функциясын ишке ашыралы:

jsxfunction editProd(id, field, event) {
  setProds(prods.map(prod => {
    if (prod.id === id) {
      prod[field] = event.target.value;
    }
    
    return prod;
  }));
}

Өнүм тегине биздин toggleMode жана editProd функцияларыбызды аттрибуттар катары берели:

jsxconst items = prods.map(prod => {
  return <Product
    key ={prod.id}
    id  ={prod.id}
    name={prod.name}
    cost={prod.cost}
    isEdit={prod.isEdit}
    toggleMode={toggleMode}
    editProd={editProd}
  />;
});

Products компонентинин акыркы коду төмөнкүдөй болот:

jsxfunction Products() {
  const [prods, setProds] = useState(initProds);
  
  function toggleMode(id) {
    setProds(prods.map(prod => {
      if (prod.id === id) {
        prod.isEdit = !prod.isEdit;
      }
      
      return prod;
    }));
  }
  
  function editProd(id, field, event) {
    setProds(prods.map(prod => {
      if (prod.id === id) {
        prod[field] = event.target.value;
      }
      
      return prod;
    }));
  }
  
  const result = prods.map(prod => {
    return <Product
      key ={prod.id}
      id  ={prod.id}
      name={prod.name}
      cost={prod.cost}
      isEdit={prod.isEdit}
      toggleMode={toggleMode}
      editProd={editProd}
    />;
  });
  
  return <div>
    {result}
  </div>;
}

Практикалык тапшырмалар

Задание 1

Өзүңүз мурунку сабактарда түзгөн Users жана User компоненттери менен ушул сыяктуу аракеттерди жүргүзүңүз.