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é