Modifica dello stato del genitore in un componente figlio in React
Ora modifichiamo i nostri prodotti utilizzando gli input. A questo scopo, nel componente figlio creiamo un pulsante.
Alla prima pressione di questo pulsante, al posto del nome e del prezzo del prodotto, appariranno gli input per modificarli, e alla seconda pressione al posto degli input appariranno di nuovo i testi.
Apportiamo una modifica all'array dei prodotti, aggiungendo
la proprietà isEdit (e per semplicità rimuoviamo
il lavoro con il carrello):
const initProds = [
{id: id(), name: 'product1', cost: 100, isEdit: false},
{id: id(), name: 'product2', cost: 200, isEdit: false},
{id: id(), name: 'product3', cost: 300, isEdit: false},
];
Componente Product
Creiamo un pulsante per la modifica nel prodotto:
function Product({ id, name, cost, isEdit }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button>edit</button>
</div>;
}
Facciamo in modo che al click su questo pulsante
venga chiamata una certa funzione toggleMode,
passata dal componente genitore:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button onClick={() => toggleMode(id)}>
edit
</button>
</div>;
}
Per ora non abbiamo l'implementazione di toggleMode,
ma sappiamo che si troverà
nel componente genitore, accetterà come parametro
l'id del prodotto e cambierà la proprietà isEdit
del prodotto al valore opposto.
Facciamo anche in modo che il testo del pulsante cambi ad ogni pressione:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button onClick={() => toggleMode(id)}>
{isEdit ? 'save': 'edit'}
</button>
</div>;
}
Ora facciamo in modo che in modalità modifica abbiamo input con i dati, e in modalità normale - degli span:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
name: {isEdit ? <input value={name} /> : <span>{name}</span>}
cost: {isEdit ? <input value={cost} /> : <span>{cost}</span>}
<button onClick={() => toggleMode(id)}>
{isEdit ? 'save': 'edit'}
</button>
</div>;
}
Colleghiamo ai nostri input l'evento onChange,
in cui chiameremo una certa funzione del genitore
editProd:
function Product({ id, name, cost, isEdit, toggleMode, editProd }) {
return <div>
name: {
isEdit
? <input value={name} onChange={event => editProd(id, 'name', event)} />
: <span>{ name }</span>
}
cost: {
isEdit
? <input value={cost} onChange={event => editProd(id, 'cost', event)} />
: <span>{ cost }</span>
}
<button onClick={() => toggleMode(id)}>
{isEdit ? 'save': 'edit'}
</button>
</div>;
}
Componente Products
Ora passiamo al componente Products.
Implementiamo in esso la funzione toggleMode:
function toggleMode(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.isEdit = !prod.isEdit;
}
return prod;
}));
}
Implementiamo anche in esso la funzione editProd:
function editProd(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
Nel tag del prodotto passiamo come attributi le nostre
funzioni toggleMode e editProd:
const items = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name={prod.name}
cost={prod.cost}
isEdit={prod.isEdit}
toggleMode={toggleMode}
editProd={editProd}
/>;
});
Il codice finale del componente Products
risulterà il seguente:
function Products() {
const [prods, setProds] = useState(initProds);
function toggleMode(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.isEdit = !prod.isEdit;
}
return prod;
}));
}
function editProd(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
const result = prods.map(prod => {
return <Product
key ={prod.id}
id ={prod.id}
name={prod.name}
cost={prod.cost}
isEdit={prod.isEdit}
toggleMode={toggleMode}
editProd={editProd}
/>;
});
return <div>
{result}
</div>;
}
Compiti pratici
Esegui operazioni simili con i componenti
Users e User, creati da te
nelle lezioni precedenti.