Modalità di funzionamento attraverso gli stati dei componenti figli in React
Supponiamo che il nostro array di prodotti ora appaia nel modo seguente:
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'},
];
Visualizziamo questi prodotti in una tabella HTML.
Allo stesso tempo, facciamo in modo che cliccando
su qualsiasi cella della tabella appaia un input
per la modifica. Per risolvere il compito creeremo
3 componenti.
Il componente Products memorizzerà lo stato
con i prodotti e utilizzerà i componenti Product
per visualizzare i prodotti. Il componente Product
a sua volta utilizzerà anche i componenti
ProductField per visualizzare un determinato
campo del prodotto (nome, prezzo, categoria).
Il componente ProductField mostrerà
o il testo del campo, o un input per la sua
modifica. Inoltre, la modalità di modifica
o visualizzazione sia regolata dallo stato
di questo componente.
Cioè, non memorizzeremo la modalità nello stato del componente genitore. Lì sarebbe molto scomodo, poiché dovremmo specificare la modalità per ogni campo del prodotto, il che trasformerebbe il nostro stato in qualcosa di simile:
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},
],
]
Tuttavia, non creeremo uno stato del genere,
ma manterremo quello che c'era. Semplicemente,
ogni istanza del componente ProductField
utilizzando il proprio stato regolerà la modalità:
modifica o visualizzazione.
In questo modo, il componente genitore conserverà lo stato con i dati, e il nostro componente nipote riceverà questi dati tramite le props e allo stesso tempo avrà il proprio stato per modificare la propria modalità.
Quindi, implementiamo quanto descritto.
Componente 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>;
}
Componente 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>;
}
Componente 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>;
}
Compiti pratici
Esegui operazioni simili con i componenti
Users e User che hai creato
nelle lezioni precedenti.