J'ai un composant qui est censé afficher une "carte" contenant des informations enregistrées dans un tableau en état. J'obtiens ces informations à partir d'un fichier JSON et je les sauvegarde dans mon tableau dans un "componentDidMount". J'ai ensuite créé une fonction appelée "displayFood" avant le retour de ma fonction de rendu, que j'utilise ensuite dans mes fonctions de rendu. Le problème est que lorsque j'exécute le code, aucune carte n'est affichée.
import React from 'react' import "./style.scss"; import FoodData from "./foodData.json"; class Food extends React.Component { constructor(props){ super(props); this.state={ foodData: [] } } componentDidMount(){ FoodData.map((foodItem,index) => { var foodTemp = { id: index, name: foodItem.name, pic: foodItem.pic, serving: foodItem.serving, calories: foodItem.calories, sugar: foodItem.sugar, protien: foodItem.protien } this.setState((prevState) => { prevState.foodData.push(foodTemp) }) }) } render() { const displayFood = () => { var i; for(i = 0; i < this.state.foodData.length; i++){ return( <div className="food-card"> <img src={require(`${this.state.foodData[i].pic}`)}/> <ul> <li>{this.state.foodData[i].name}</li> <li>Serving: {this.state.foodData[i].serving}</li> <li>Calories: {this.state.foodData[i].calories}</li> <li>Sugar: {this.state.foodData[i].sugar}</li> <li>Protien: {this.state.foodData[i].protien}</li> </ul> <button name={this.state.foodData[i].name}>Add</button> </div> ) } } return( <div> <div className="food-container"> { displayFood() } </div> </div> ) } } export default Food;
4 Réponses :
Selon le cycle de vie, la méthode render
est en fait déjà appelée avant componentDidMount
. Par conséquent, au moment où elles sont rendues, les données sont toujours vides. Pourquoi ne pas déplacer l'initialisation des données dans componentWillMount
?
Merci justelouise je suis allé de l'avant et j'ai changé le "DidMount" en "WillMount" et maintenant il affiche correctement le premier objet du tableau. J'espère que je pourrai comprendre pourquoi la boucle for ne me donne qu'un seul résultat. (j'ai essayé de vous voter mais parce que je n'ai pas de réputation sur ce site, cela ne montrera pas)
essayez de changer l'état précédent ... vous avez utilisé directement les données sur l'état, cela ne change pas la racine de l'état:
this.setState((prevState) => ({ ...prevState, foodData: [ ...foodData, foodTemp ], }))
Merci d'avoir apporté les modifications et obtenir le même résultat du programme affichant uniquement le premier élément dans le tableau d'état
Premièrement, je ne suis pas sûr que votre setState
dans componentDidMount
fonctionne. Si vous ne souhaitez pas renvoyer un nouveau tableau, vous ne devez pas utiliser map
, utilisez plutôt forEach
. Et vous faites muter directement l'état, ce qui n'est pas recommandé. La fonction devrait ressembler à ceci:
const displayFood = () => { let cards = [] // Crate an array for(let i = 0; i < this.state.foodData.length; i++){ cards.push( // push item to array through the loop <div className="food-card"> <img src={require(`${this.state.foodData[i].pic}`)}/> <ul> <li>{this.state.foodData[i].name}</li> <li>Serving: {this.state.foodData[i].serving}</li> <li>Calories: {this.state.foodData[i].calories}</li> <li>Sugar: {this.state.foodData[i].sugar}</li> <li>Protien: {this.state.foodData[i].protien}</li> </ul> <button name={this.state.foodData[i].name}>Add</button> </div> ) } return cards // Return the array }
Deuxièmement, return
dans la boucle for
ne renverra que le premier élément. Vous devez créer un tableau puis pousser l'élément à travers la boucle au lieu de retourner
componentDidMount(){ // Build a new array of object from FoodData const newFoodData = FoodData.map(({name, pic, serving, calories, sugar, protien }, index) => ({ id: index, name, pic, serving, calories, sugar, protien })) // Assign the new object to state this.setState({ foodData: newFoodData }) }
Et je vous recommande de déplacer le displayFood
en dehors du rendu ()
fonction. Parce que lorsque d'autres choses provoquent un nouveau rendu mais pas le changement de this.state.foodData
, le composant doit reconstruire le displayFood ()
. C'est gaspillé.
Dam bird vous l'avez cloué sur la tête. J'ai mis en œuvre vos suggestions en changeant le "DidMount" en "WillMount" et cela fonctionne très bien. J'aurais aimé avoir plus de réputation de stackoverflow pour vous donner un vote positif visible. Merci encore
Je vous en prie! En fait, vous devriez le mettre dans componentDidMount
, il suffit d'ajouter handle le fooData vide dans la fonction render (). c'est-à-dire if (! this.state.dataFood.length) renvoie
. Parce que, dans une application réelle, les données ne proviendront pas du fichier JSON mais de l'API, Loading...
componentWillMount
ne peut pas vous aider à ce moment-là. Et à partir de la version 17, 'componentWillMount' sera obsolète reactjs.org/docs/react-component .html # unsafe_componentwillmo unt
Grand à savoir et fera. J'ai entendu parler de la dépréciation de "compnentWillMount" mais je ne l'avais pas encore examiné. Vous semblez très bien informé sur React.
class Hello extends React.Component { constructor(props){ super(props); this.state={ foodData: [] } } componentDidMount(){ const { foodData } = this.state; foodData.push({ id: 0, name: 'beans', pic: 'picurl', serving: '2', calories: '100', sugar: '30', protien: '10' }); this.setState({ foodData }); } render() { return <div> <div className="food-container"> { this.state.foodData.map((item,key) => { return <div className="food-card"> {`${item.pic}`} <ul> <li>{item.name}</li> <li>Serving: {item.serving}</li> <li>Calories: {item.calories}</li> <li>Sugar: {item.sugar}</li> <li>Protien: {item.protien}</li> </ul> <button name={item.name}>Add</button> </div> }) } </div> </div>; } } ReactDOM.render( <Hello />, document.getElementById('container') ); make sure that your foodData is loaded correctly on 'componentDidMount()'https://jsfiddle.net/leolima/L7c418kp/13/
Merci pour la réponse Leo. Il semble que cela fonctionnerait également, mais j'ai déjà une réponse solide de Bird. Merci de votre aide.