Werkmodi via staten van onderliggende componenten in React
Laten we aannemen dat onze array met producten er nu als volgt uitziet:
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'},
];
Laten we deze producten weergeven als een HTML
tabel. Laten we het zo maken dat wanneer er op een
willekeurige cel in de tabel wordt geklikt,
er een invoerveld verschijnt in die cel voor bewerking.
Om de taak op te lossen maken we 3 componenten.
De component Products zal de staat
met producten opslaan en componenten Product
gebruiken om producten weer te geven. De component Product
zal op zijn beurt ook componenten
ProductField gebruiken om een specifiek
veld van het product weer te geven (naam, prijs, categorie).
De component ProductField zal ofwel
de tekst van het veld tonen, of een invoerveld voor
het bewerken ervan.
Laat de bewerkingsmodus
of weergavemodus worden geregeld door de staat
van deze component.
Dat betekent dat we de modus niet zullen opslaan in de bovenliggende staat. Dat zou daar erg onhandig zijn, omdat we de modus voor elk veld van het product zouden moeten opgeven, wat onze staat zou veranderen in zoiets als:
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},
],
]
We zullen echter zo'n staat niet maken,
maar de originele behouden.
Elk exemplaar van de component ProductField
zal met behulp van zijn eigen staat de modus regelen:
ofwel bewerken, ofwel weergeven.
Zo zal het blijken dat de bovenliggende component de staat met gegevens zal opslaan, terwijl onze onderliggende component deze gegevens via props ontvangt en tegelijkertijd zijn eigen staat zal hebben om zijn modus te wijzigen.
Laten we dus het beschrevene implementeren.
Component 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>;
}
Component 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>;
}
Component 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>;
}
Praktische taken
Voer vergelijkbare bewerkingen uit met de componenten
Users en User, die je hebt gemaakt
in eerdere lessen.