Reputation: 307
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
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
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
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