Arbeitsmodi über States von Child-Komponenten in React
Nehmen wir an, unser Produktarray sieht nun wie folgt aus:
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'},
];
Lassen Sie uns diese Produkte als HTML-Tabelle
ausgeben. Dabei sorgen wir dafür, dass beim Klick
auf eine beliebige Zelle der Tabelle in dieser Zelle
ein Input zum Bearbeiten erscheint. Um die Aufgabe
zu lösen, erstellen wir 3 Komponenten.
Die Komponente Products wird den State
mit den Produkten halten und die Komponenten Product
zur Ausgabe der Produkte verwenden. Die Komponente Product
wiederum wird ebenfalls die Komponenten
ProductField zur Ausgabe eines bestimmten
Produktfelds (Name, Preis, Kategorie) verwenden.
Die Komponente ProductField zeigt entweder
den Text des Felds an oder einen Input zu dessen
Bearbeitung. Dabei soll der Bearbeitungsmodus
oder Anzeigemodus durch den State dieser Komponente gesteuert werden.
Das heißt, wir werden den Modus nicht im übergeordneten State speichern. Das wäre dort sehr unpraktisch, da wir den Modus für jedes Feld jedes Produkts angeben müssten, was unseren State in so etwas verwandeln würde:
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},
],
]
Wir werden jedoch einen solchen State nicht erstellen,
sondern den beibehalten, den wir hatten. Einfach wird jede
Instanz der Komponente ProductField
mit Hilfe ihres eigenen States den Modus steuern:
entweder Bearbeitung oder Anzeige.
So ergibt sich, dass die übergeordnete Komponente den State mit den Daten hält, und unsere Enkelkomponente diese Daten über Props erhält und dabei einen eigenen State zur Änderung ihres Modus haben wird.
Lassen Sie uns das Beschriebene nun implementieren.
Komponente 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>;
}
Komponente 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>;
}
Komponente 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>;
}
Praktische Aufgaben
Führen Sie ähnliche Operationen mit den Komponenten
Users und User durch, die Sie
in vorherigen Lektionen erstellt haben.