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:
import React, { Component } from 'react';
import axios from 'axios';
class Products extends Component {
state = {
MetaProducts: []
}
async ponentDidMount(){
const res = await axios.get('')
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) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
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./walmartproducts/1/20
import React, { Component } from 'react';
import axios from 'axios';
class Products extends Component {
state = {
MetaProducts: []
}
async ponentDidMount(){
const res = await axios.get('https://mobile-tha-server-8ba57.firebaseapp./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) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
3 Answers
Reset to default 3This is because in React ponentDidMount is called after the render method.
Check the React lifecycle methods here https://reactjs/docs/react-ponent.html#mounting.
It is logging the empty array first which is the default state and then whatever was returned by the axios api call.
This is because of the asynchronous behaviour of the react life cycles . Your render is called before the pletion 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 pletion 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 ponentDidMount() {
await axios.get('https://mobile-tha-server-8ba57.firebaseapp./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;
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 ponentDidMount
. Because you initiate the MetaProducts
as an empty arrray, thats why it will print and empty array first.