Modes de fonctionnement via les états des composants enfants dans React
Supposons que notre tableau de produits ressemble maintenant à ceci :
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'},
];
Affichons ces produits sous forme de tableau HTML.
Faisons en sorte qu'un clic sur n'importe quelle cellule du tableau
fasse apparaître un champ de saisie pour la modifier. Pour résoudre cette tâche,
nous créerons 3 composants.
Le composant Products stockera l'état
des produits et utilisera les composants Product
pour afficher les produits. Le composant Product
utilisera à son tour les composants
ProductField pour afficher un champ spécifique
du produit (nom, prix, catégorie).
Le composant ProductField affichera soit
le texte du champ, soit un champ de saisie pour
le modifier. Le mode édition ou affichage
sera régulé par l'état de ce composant.
C'est-à-dire que nous ne stockerons pas le mode dans l'état du parent. Cela serait très peu pratique ici, car nous devrions spécifier le mode pour chaque champ de produit, ce qui transformerait notre état en quelque chose comme ceci :
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},
],
]
Cependant, nous ne créerons pas un tel état,
et garderons celui qui existait. Simplement, chaque
instance du composant ProductField
régulera son mode via son propre état :
soit l'édition, soit l'affichage.
Ainsi, le composant parent stockera l'état avec les données, et notre composant petit-enfant recevra ces données via les props tout en ayant son propre état pour changer son mode.
Maintenant, implémentons ce qui a été décrit.
Composant 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>;
}
Composant 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>;
}
Composant 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>;
}
Tâches pratiques
Répétez des opérations similaires avec les composants
Users et User que vous avez créés
dans les leçons précédentes.