Рэжымы працы праз стэйты кампанентаў-нашчадкаў у 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, створанымі вамі
у папярэдніх уроках.