88dax
88dax

Reputation: 307

Axios returning empty array before returning the data

I have a simple react app which pulls data from an API and prints it to the console. I'm using Axios to get the values from API. Here is the API: https://mobile-tha-server-8ba57.firebaseapp.com/walmartproducts/1/20

import React, { Component } from 'react';
import axios from 'axios';

class Products extends Component {
    state = {
        MetaProducts: []
    }
    async componentDidMount(){
        const res = await axios.get('https://mobile-tha-server-8ba57.firebaseapp.com/walmartproducts/1/20')
        this.setState({ MetaProducts: res.data.products});
    }

    render() {
        console.log(this.state.MetaProducts);
        return(
            <div>
                Products
            </div>

        )
    }
}


export default Products;

But Axios, first returns an empty array and then returns the array with data.

console:
Products.js:14 []
Products.js:14 (20) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

Upvotes: 2

Views: 5381

Answers (3)

sumit
sumit

Reputation: 15464

This is because of the asynchronous behaviour of the react life cycles . Your render is called before the completion of your axios request and this.state.Metaproducts was never updated inside render as it was already rendered before your request . You can wait for the callback from the axios and then update the state only after that and make sure to render the product after the completion of ajax.

I have added one more state variable init , and set that as true after getting response from server . By default init will be false and then you can show the "loading message " .

Hope it will help you

import React, { Component } from 'react';
import axios from 'axios';

class Products extends Component {
  state = {
    MetaProducts: [],
    init:0,
  }

  async componentDidMount() {
   await axios.get('https://mobile-tha-server-8ba57.firebaseapp.com/walmartproducts/1/20').then(res => {
      this.setState({ MetaProducts: res.data.products, init:1 });
    });
  }

  renderProduct() {
    return <ul>
    {this.state.MetaProducts.map(p =>
      <li>
        {p.productName}
      </li>
    )};
    </ul>;
  }

  render() {
    return this.state.init ? <div>{this.renderProduct()}</div> : <div>loading...</div>;
   }
}



export default Products;

Upvotes: 1

user10454516
user10454516

Reputation: 1143

Did you mean empty array on the console? Sure. It will print empty array. You have to take a look at react lifecycle. Render will run first, then the next is componentDidMount. Because you initiate the MetaProducts as an empty arrray, thats why it will print and empty array first.

Upvotes: 1

prabhat
prabhat

Reputation: 635

This is because in React componentDidMount is called after the render method.

Check the React lifecycle methods here https://reactjs.org/docs/react-component.html#mounting.

It is logging the empty array first which is the default state and then whatever was returned by the axios api call.

Upvotes: 3

Related Questions