Načini delovanja preko stanj komponent-potomcev v React
Naj bo naš seznam izdelkov zdaj videti takole:
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'},
];
Izpišimo te izdelke v obliki HTML
tabele. Pri tem naredimo tako, da se ob kliku
na katero koli celico tabele v tej celici pojavi
vnosno polje za urejanje. Za rešitev naloge
naredimo 3 komponente.
Komponenta Products bo hranila stanje
z izdelki in uporabljala komponente Product
za prikaz izdelkov. Komponenta Product
bo prav tako uporabljala komponente
ProductField za prikaz določenega
polja izdelka (ime, cena, kategorija).
Komponenta ProductField bo pokazala bodisi
besedilo polja bodisi vnosno polje za njegovo
urejanje. Pri tem naj se način urejanja
ali prikaza regulira s stanjem
te komponente.
To pomeni, da načina ne bomo hranili v nadrejenem stanju. Tam bi bilo to zelo neprijetno, saj bi morali navesti način za vsako polje izdelka, kar bi spremenilo naše stanje v nekaj podobnega:
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},
],
]
Vendar mi ne bomo naredili takšnega stanja,
ampak bomo obdržali tistega, ki je bil.
Preprosto bo vsak
primer komponente ProductField
s pomočjo svojega stanja reguliral
način: bodisi urejanje, bodisi prikaz.
Tako se bo izkazalo, da bo nadrejena komponenta hranila stanje s podatki, naša vnukinja komponenta pa bo te podatke prejela preko propov in bo imela svoje stanje za spreminjanje svojega načina.
Torej, implementirajmo opisano.
Komponenta 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>;
}
Komponenta 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>;
}
Komponenta 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>;
}
Praktične naloge
Izvedite podobne operacije s komponentami
Users in User, ki ste jih ustvarili
v prejšnjih lekcijah.