【问题标题】:React component wont display the return of a functionReact 组件不会显示函数的返回
【发布时间】:2019-08-11 20:16:16
【问题描述】:

我有一个组件应该显示一个“卡片”,其中包含保存在状态数组中的信息。我从 JSON 文件中获取此信息并将其保存到我的数组中的“componentDidMount”中。然后我在我的渲染函数返回之前创建了一个名为“displayFood”的函数,然后我在我的渲染函数返回中使用它。问题是当我运行代码时没有显示任何卡片。

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;

【问题讨论】:

    标签: javascript arrays reactjs state render


    【解决方案1】:

    根据生命周期,render 方法实际上在componentDidMount 之前已经被调用过。因此,当它被渲染时,数据仍然是空的。为什么不在componentWillMount 中移动数据初始化?

    【讨论】:

    • 感谢 justelouise 我继续将“DidMount”更改为“WillMount”,现在它正确显示了数组中的第一个对象。希望我可以解决为什么 for 循环只给我一个结果。 (我试图给你投票,但因为我在这个网站上没有声誉,所以不会显示)
    【解决方案2】:

    尝试改变之前的状态......你直接使用了状态数据,它不会改变状态根:

    this.setState((prevState) => ({
        ...prevState,
        foodData: [ ...foodData, foodTemp ],
    }))
    

    【讨论】:

    • 感谢我进行了更改并获得了与程序相同的结果,仅显示状态数组中的第一项
    【解决方案3】:

    首先,我不确定您的 setState incomponentDidMount 工作。如果你不想返回一个新数组,你不应该使用map,而是使用forEach。而且您正在直接改变状态,这是不推荐的。函数应该是这样的:

    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 })
    }
    

    其次,for 循环中的return 将只返回第一项。您应该创建一个数组,然后通过循环推送项目而不是返回

    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
    }
    

    我建议您将displayFood 移到render() 函数之外。因为当其他事情导致重新渲染而不是this.state.foodData 更改时,组件必须重新构建displayFood()。浪费了。

    【讨论】:

    • 大坝鸟,你把它钉在了头上。我实施了您的建议,并将“DidMount”更改为“WillMount”,效果很好。我希望我有更多的 stackoverflow 声誉给你一个可见的支持。再次感谢
    • 不客气!实际上,你应该把它放在componentDidMount 中,只需在render() 函数中添加处理空的fooData 即可。即if(!this.state.dataFood.length) return &lt;h1&gt;Loading...&lt;/h1&gt;。因为,在真正的 App 中,数据不会来自 JSON 文件,而是来自 API,componentWillMount 到时候帮不了你。从版本 17 开始,'componentWillMount' 将被弃用 reactjs.org/docs/react-component.html#unsafe_componentwillmount
    • 很高兴知道并且会这样做。我听说过“compnentWillMount”的弃用,但还没有调查过。你似乎对 React 非常了解。
    【解决方案4】:
    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')
    );
    
    
    

    确保您的 foodData 在 'componentDidMount()' 上正确加载

    https://jsfiddle.net/leolima/L7c418kp/13/

    【讨论】:

    • 感谢 Leo 的回复。看起来这也可行,但我已经从伯德那里得到了可靠的答案。不过感谢您的帮助。
    猜你喜欢
    • 2013-08-02
    • 2013-09-24
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    相关资源
    最近更新 更多