Режими рада преко стејтова компонената-потомака у 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, које сте креирали
у претходним лекцијама.