# Редактирование стейта родителя в дочернем компоненте в React

Давайте теперь будем редактировать наши продукты с помощью инпутов. Для этого в дочернем компоненте сделаем кнопку.

По первому нажатию на эту кнопку пусть вместо названия и цены с продуктом появятся инпуты для их редактирования, а по второму нажатию вместо инпутов опять появятся тексты.

Внесем изменение в массив с продуктами, добавив свойство `isEdit` (а работу с корзиной для простоты уберем):

`const 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

Сделаем в продукте кнопку для редактирования:

`function Product({ id, name, cost, isEdit }) { return <div> name: <span>{name}</span> cost: <span>{cost}</span> <button>edit</button> </div>; }`

Сделаем так, чтобы по клику на эту кнопку вызвалась некоторая функция `toggleMode`, переданная из родительского компонента:

`function Product({ id, name, cost, isEdit, toggleMode }) { return <div> name: <span>{name}</span> cost: <span>{cost}</span> <button onClick={() => toggleMode(id)}> edit </button> </div>; }`

Пока у нас нет реализации `toggleMode`, но мы знаем, что она будет располагаться в компоненте-родителе, параметром принимать `id` продукта и изменять свойство `isEdit` продукта на противоположное.

Сделаем также так, чтобы текст кнопки менялся каждое нажатие:

`function Product({ id, name, cost, isEdit, toggleMode }) { return <div> name: <span>{name}</span> cost: <span>{cost}</span> <button onClick={() => toggleMode(id)}> {isEdit ? 'save': 'edit'} </button> </div>; }`

Давайте теперь сделаем так, чтобы в режиме редактирования у нас были инпуты с данными, а в обычном режиме - спены:

`function Product({ id, name, cost, isEdit, toggleMode }) { return <div> name: {isEdit ? <input value={name} /> : <span>{name}</span>} cost: {isEdit ? <input value={cost} /> : <span>{cost}</span>} <button onClick={() => toggleMode(id)}> {isEdit ? 'save': 'edit'} </button> </div>; }`

Привяжем к нашим инпутам событие `onChange`, в котором будем вызывать некоторую родительскую функцию `editProd`:

`function Product({ id, name, cost, isEdit, toggleMode, editProd }) { return <div> name: { isEdit ? <input value={name} onChange={event => editProd(id, 'name', event)} /> : <span>{ name }</span> } cost: { isEdit ? <input value={cost} onChange={event => editProd(id, 'cost', event)} /> : <span>{ cost }</span> } <button onClick={() => toggleMode(id)}> {isEdit ? 'save': 'edit'} </button> </div>; }`

## Компонент Products

Давайте теперь перейдем в компонент `Products`. Реализуем в нем функцию `toggleMode`:

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

Также реализуем в нем функцию `editProd`:

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

В тег с продуктом атрибутами передадим наши функции `toggleMode` и `editProd`:

`const 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` получится следующим:

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

## Практические задачи

Проделайте аналогичные операции с компонентами `Users` и `User`, созданными вами в предыдущих уроках.

←→
↑