0

I'm struggling with fetching data and render to the screen in React JS

class Home extends Component{
    componentWillMount(){
        foods=[];
        fetch('http://192.249.19.243:0280/main/get_recipes')
            .then(res => res.json())
            .then(data => foodlist=data)
            .then(
                () => console.log("f:",foodlist),
            )
            .then(
                () => {foodlist.map(item => foods.push({title:item, img:"http://192.249.19.243:0280/main/image/"+item}));
                    console.log("foods", foods);
                    this.render();
                }
        );
}
componentDidMount(){
}

render(){
    console.log("render in!");
    return (
        <div>
            <ul>
                {
                    console.log(foods), // this works fine -> 4 elements
                    foods.length!=0 ?
                    foods.map(item=>
                        <Item 
                            title={item.title} 
                            img={item.img}/>
                        )
                    :
                        <p id="loadingMsg">Data Loading...</p>
                }
            </ul>
        </div>
        );
    }
}
export default Home;

in the render(), I checked console.log(foods) print 4 elements, but Nothing appears in the screen..

I don't know why.. Please help me..

0

3 Answers 3

2

In react: it is not you who manage the render. If you want to render an element you need to call this.setState with the data that changed. You can see my example:

class Home extends Component{
state = { 
foods: []
}
    componentWillMount(){
        fetch('http://192.249.19.243:0280/main/get_recipes')
            .then(res => res.json())
            .then(data => foodlist=data)
            .then(
                () => console.log("f:",foodlist),
            )
            .then(
                () => {
this.setState({foods: foodlist.map(item => ({title:item, img:"http://192.249.19.243:0280/main/image/"+item})));
                }
        );
}
componentDidMount(){
}

render(){
    console.log("render in!");
    return (
        <div>
            <ul>
                {
                    this.state.foods.length!=0 ?
                    this.state.foods.map(item=>
                        <Item 
                            title={item.title} 
                            img={item.img}/>
                        )
                    :
                        <p id="loadingMsg">Data Loading...</p>
                }
            </ul>
        </div>
        );
    }
}
export default Home;
Sign up to request clarification or add additional context in comments.

1 Comment

it says " 'foods' is not defined no-undef " in this.setState({ foods: foodlist.map(item => foods.push({title:item, img:"192.249.19.243:0280/main/image/"+item}))}); this part...
0

It looks like you are relatively new to React. I spot quite a few errors with this.

Please read the docs on class based components carefully

I have tried to refactor it without context. Give it a bash

class Home extends Component {

  //initialize state in the constructor for class based components
  constructor(props) {
    super(props);
    //foods must be an empty array otherwise .length may fail
    this.state = { foods: [] }
  };

  //once the component has mounted, call the method which will perform the fetch
  componentDidMount() {
    this.fetchFoodData();
  }

  //calls the endpoint which returns a promise. The promise will then set the components state, which will trigger a render
  fetchFoodData = () => {
    fetch('http://192.249.19.243:0280/main/get_recipes')
      .then(res => {
        const foodData = res.json();
        //not sure what your body looks like, but foods should be an array containing your food objects
        const foods = foodData.map(item => foods.push({ title: item, img: "http://192.249.19.243:0280/main/image/" + item}));
        //calling setState will cause react to call the render method.
        this.setState({ foods: foods })
      }).catch(err => {
        //handle errors here
        console.log(err);
      });
  };
  //React calls this method when props or state change for this component
  render() {
    return (
      <div>
        <ul>
          {
            foods.length != 0 ?
              foods.map(item =>
                <Item
                  title={item.title}
                  img={item.img} />
              )
              :
              <p id="loadingMsg">Data Loading...</p>
          }
        </ul>
      </div>
    );
  }
}
export default Home;

Comments

0

Thats not the correct way to handle data in a react component. You should maintain list of foods in component state. Code sandbox: https://codesandbox.io/s/falling-bush-b9b78 As an example

import React from "react";

export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      foods: []
    };
  }
  componentDidMount() {
    const fetchMock = url =>
      new Promise(resolve => {
        setTimeout(() => resolve(["Barley", "Chicken", "Oats"]), 2000);
      });
    fetchMock("http://192.249.19.243:0280/main/get_recipes").then(foods => {
      this.setState({
        foods
      });
    });
  }

  render() {
    console.log("render in!");
    const { foods } = this.state;
    return (
      <div>
        <ul>
          {foods.length !== 0 ? (
            foods.map(food => <h1 key={food}>{food}</h1>)
          ) : (
            <p id="loadingMsg">Data Loading...</p>
          )}
        </ul>
      </div>
    );
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.