Arbeidsmoduser via tilstander i underkomponenter i React
La oss si at vår matrise med produkter nå ser slik ut:
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'},
];
La oss vise disse produktene som en HTML
tabell. La oss også gjøre det slik at når du klikker
på en hvilken som helst celle i tabellen, dukker det opp
et inndatafelt for redigering i den cellen. For å løse oppgaven
vil vi lage 3 komponenter.
Komponenten Products vil lagre tilstanden
med produktene og bruke komponentene Product
for å vise produktene. Komponenten Product
vil i sin tur også bruke komponentene
ProductField for å vise et bestemt
felt for produktet (navn, pris, kategori).
Komponenten ProductField vil enten
vise feltets tekst, eller et inndatafelt for å
redigere det. La redigeringsmodusen
eller visningsmodusen reguleres av denne komponentens tilstand.
Det vil si at vi ikke vil lagre modusen i den overordnede tilstanden. Det ville vært veldig upraktisk der, siden vi måtte angi modus for hvert felt i produktet, noe som ville gjort tilstanden vår til noe slikt:
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},
],
]
Vi vil imidlertid ikke lage en slik tilstand,
men beholde den vi hadde. Bare hver
forekomst av komponenten ProductField
ved hjelp av sin egen tilstand vil regulere
modusen: enten redigering eller visning.
På denne måten vil det skje at den overordnede komponenten vil lagre tilstanden med dataene, og vår barnekomponent vil motta disse dataene gjennom props og samtidig ha sin egen tilstand for å endre sin modus.
Så, la oss implementere det som er beskrevet.
Komponenten 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>;
}
Komponenten 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>;
}
Komponenten 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>;
}
Praktiske oppgaver
Gjør de samme operasjonene med komponentene
Users og User, som du opprettet
i tidligere leksjoner.