Bearbeiten des Parent-State in einer Child-Komponente in React
Lass uns nun unsere Produkte mit Hilfe von Inputs bearbeiten. Dazu erstellen wir eine Schaltfläche in der Child-Komponente.
Beim ersten Klick auf diese Schaltfläche sollen anstelle des Namens und des Preises des Produkts Inputs zu deren Bearbeitung erscheinen, und beim zweiten Klick anstelle der Inputs wieder die Texte.
Nehmen wir eine Änderung im Produktarray vor, indem wir
eine Eigenschaft isEdit hinzufügen
(und der Einfachheit halber entfernen wir die Arbeit mit dem Warenkorb):
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},
];
Komponente Product
Erstellen wir eine Schaltfläche zur Bearbeitung im Produkt:
function Product({ id, name, cost, isEdit }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button>edit</button>
</div>;
}
Sorgen wir dafür, dass beim Klick auf diese Schaltfläche
eine bestimmte Funktion toggleMode aufgerufen wird,
die von der Parent-Komponente übergeben wird:
function Product({ id, name, cost, isEdit, toggleMode }) {
return <div>
name: <span>{name}</span>
cost: <span>{cost}</span>
<button onClick={() => toggleMode(id)}>
edit
</button>
</div>;
}
Noch haben wir keine Implementierung von toggleMode,
aber wir wissen, dass sie sich in der Parent-Komponente befinden wird,
die id des Produkts als Parameter entgegennimmt
und die Eigenschaft isEdit des Produkts
auf den gegenteiligen Wert setzt.
Sorgen wir auch dafür, dass sich der Text der Schaltfläche bei jedem Klick ändert:
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>;
}
Lass uns nun dafür sorgen, dass im Bearbeitungsmodus Inputs mit den Daten angezeigt werden, und im normalen Modus - Spans:
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>;
}
Binden wir an unsere Inputs das Ereignis onChange,
in dem wir eine bestimmte Parent-Funktion
editProd aufrufen werden:
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>;
}
Komponente Products
Lass uns nun zur Komponente Products wechseln.
Implementieren wir darin die Funktion toggleMode:
function toggleMode(id) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod.isEdit = !prod.isEdit;
}
return prod;
}));
}
Implementieren wir darin auch die Funktion editProd:
function editProd(id, field, event) {
setProds(prods.map(prod => {
if (prod.id === id) {
prod[field] = event.target.value;
}
return prod;
}));
}
Übergeben wir unsere Funktionen toggleMode und editProd
als Attribute im Produkt-Tag:
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}
/>;
});
Der endgültige Code der Komponente Products
wird wie folgt aussehen:
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>;
}
Praktische Aufgaben
Führe ähnliche Operationen mit den Komponenten
Users und User durch, die du
in vorherigen Lektionen erstellt hast.