J'ai défini mon objet d'état initial comme ceci:
const Double = e => {
SetItem(Item.foodNutrients.forEach(foodNutrient => foodNutrient.value *= 2))
console.log(Item)
}
Je souhaite modifier mon objet existant en effectuant une boucle sur le tableau foodNutrient et en doublant la valeur en cliquant sur le bouton, puis en stockant l'objet mis à jour dans le hook useState.
const [Item,SetItem] = useState(
{
description: "Chicken",
foodNutrients:[
{nutrientName: "Protein", nutrientNumber: "203", value: 10},
{nutrientName: "Fat", nutrientNumber: "204", value: 15},
{nutrientName: "Carbs", nutrientNumber: "205", value: 20}
]
}
)
il enregistre le résultat correct sur la console la première fois que j'essaye de cliquer sur <button onClick={Double}>Set state</button> , mais la deuxième fois, il lance Cannot read property 'foodNutrients' of undefined et je ne peux rien rendre.
3 Réponses :
La logique de votre gestionnaire d'événements remplace l'objet initial par undefined car Array.prototype.forEach renvoie undefined par défaut.
Ce que vous devez faire est:
map vers un tableau avec de nouvelles valeursconst Double = (e) => {
const foodNutrientsNew = Item.foodNutrients.map((foodNutrient) => ({
...foodNutrient,
value: foodNutrient.value * 2,
}));
SetItem((prev) => ({ ...prev, foodNutrients: foodNutrientsNew }));
};
MISE À JOUR
Je suggérerais également de refactoriser votre code et de le diviser en plusieurs composants. Suivez simplement l'article officiel de la documentation ici
@EstusFlask est d'accord. fixé
Une bien meilleure approche consiste à le faire dans le gestionnaire onClick à la place -
const Double = e => {
// clone your Item object
const cloneItem = {...Item};
// now make modifications in the new object
cloneItem.foodNutrients.forEach(foodNutrient => foodNutrient.value *=2 );
SetItem(cloneItem);
// to see the difference in console
console.log(cloneItem)
console.log(Item)
}
J'ai essayé beaucoup de choses pour vous aider et j'ai trouvé cette solution qui fonctionne pour moi.
function App() {
const [item, setItem] = useState({
description: "Chicken",
foodNutrients: [
{ nutrientName: "Protein", nutrientNumber: "203", value: 10 },
{ nutrientName: "Fat", nutrientNumber: "204", value: 15 },
{ nutrientName: "Carbs", nutrientNumber: "205", value: 20 },
],
});
console.log(item);
const double = (e) => {
setItem({...item}, item.foodNutrients.map(e => e.value *=2));
}
return <button onClick={double}>Set state</button>;
}
L'état React est généralement supposé être immuable, il devrait être immuable en cas de hook
useState. Cela signifie qu'il devrait y avoir un nouvel objet lorsqu'un état est changé