Arbetslägen via state i underkomponenter i React
Låt vår produktarray nu se ut så här:
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'},
];
Låt oss visa dessa produkter som en HTML
tabell. Låt oss också göra så att när man klickar
på vilken cell som helst i tabellen visas en
inmatningsruta för redigering i den cellen. För att lösa uppgiften
kommer vi att skapa 3 komponenter.
Komponenten Products kommer att lagra state
med produkter och använda komponenter Product
för att visa produkter. Komponenten Product
kommer i sin tur också att använda komponenter
ProductField för att visa ett specifikt
produktfält (namn, pris, kategori).
Komponenten ProductField kommer antingen
visa fältets text, eller en inmatningsruta för att
redigera den.
Samtidigt låter vi redigeringsläget
eller visningen regleras av denna komponents state.
Det vill säga vi kommer inte att lagra läget i föräldrakomponentens state. Det skulle vara väldigt obekvämt där, eftersom vi skulle behöva ange läge för varje produktfält, vilket skulle förvandla vårt state till något liknande:
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 kommer dock inte att skapa ett sådant state,
utan behåller det som fanns. Varje
instans av komponenten ProductField
kommer med hjälp av sitt eget state reglera
läget: antingen redigering eller visning.
Således kommer föräldrakomponenten att lagra state med data, och vår barnbarnskomponent kommer att få dessa data via props och samtidigt ha ett eget state för att ändra sitt läge.
Så, låt oss implementera det som beskrivits.
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>;
}
Praktiska uppgifter
Utför liknande operationer med komponenterna
Users och User som du skapade
i tidigare lektioner.