# Режимы работы через стейты компонентов-потомков в React

Пусть наш массив с продуктами теперь выглядит следующим образом:

`const 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` будет либо показывать текст поля, либо инпут для его редактирования. При этом режим редактирования или показа пусть регулируется стейтом данного компонента.

То есть мы не будем хранить режим в родительском стейте. Там это было бы очень неудобно, так как нам пришлось бы указывать режим для каждого поля продукта, что превратило бы наш стейт в нечто подобное:

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

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

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

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

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

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

←→
↑