Moduri de lucru prin stările componentelor descendente în React
Să presupunem că array-ul nostru cu produse arată acum în felul următor:
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'},
];
Să afișăm aceste produse sub forma unui tabel HTML.
În același timp, să facem astfel încât la click pe
orice celulă a tabelului să apară un input pentru editare.
Pentru a rezolva problema vom face 3 componente.
Componenta Products va stoca starea
cu produsele și va folosi componentele Product
pentru afișarea produselor. Componenta Product
la rândul ei va folosi și componentele
ProductField pentru afișarea unui anumit
câmp al produsului (nume, preț, categorie).
Componenta ProductField va afișa fie
textul câmpului, fie un input pentru
editarea acestuia. În acest caz, modul de editare
sau afișare să fie reglat de starea
acestei componente.
Adică nu vom stoca modul în starea părinte. Acolo ar fi foarte incomod, deoarece ar trebui să indicăm modul pentru fiecare câmp al produsului, ceea ce ar transforma starea noastră în ceva similar cu:
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},
],
]
Noi, totuși, nu vom face o astfel de stare,
ci vom păstra cea care a fost.
Pur și simplu fiecare
instanță a componentei ProductField
cu ajutorul stării sale va regla
modul: fie editare, fie afișare.
Astfel, se va întâmpla că componenta părinte va stoca starea cu datele, iar componenta noastră strănepoată va primi aceste date prin props și în același timp va avea propria sa stare pentru a-și schimba modul.
Așadar, să implementăm cele descrise.
Componenta 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>;
}
Componenta 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>;
}
Componenta 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>;
}
Probleme practice
Efectuați operații similare cu componentele
Users și User, create de dvs.
în lecțiile anterioare.