I'm in process of learning React (currently high order component) and I have one problem. In my exercise, component sometimes display data and sometimes don't. My code consist of two Component
DisplayList - component that show data passed by props
GetAndDisplayData - high order component that receive DisplayList component, url of API, and desired parameter (to take from API)
Code:
DisplayList.js
class DisplayList extends React.Component{
render(){
return(
<ul>
{this.props.data.map((input, i) => <li key={i}>{input}</li>)}
</ul>
);
}
}
GetAndDisplayData.js
const GetAndDisplayData = (DisplayList, urlOfData, parameterToGet) =>
class GetAndDisplayDataClass extends React.Component{
constructor(props){
super(props);
this.state = {
loading: true,
urlOfData: urlOfData,
parameterToGet: parameterToGet,
data: []
}
}
componentDidMount(){
this.getData(urlOfData, parameterToGet)
}
getData(urlOfData,parameterToGet){
fetch(urlOfData)
.then(data => data.json())
.then(jsonData => {
jsonData.map(input =>
this.state.data.push(eval("input."+parameterToGet))
);
})
this.setState({loading: false})
console.log(this.state.data)
}
render(){
if(this.state.loading){
return(<p>Data is loading</p>)
}else{
return(
<div>
<p>Data loaded</p>
<DisplayList data={this.state.data} />
</div>
);
}
}
}
And call of HOC
render(){
const GetData = GetAndDisplayData(DisplayList, "https://restcountries.eu/rest/v1/all", "name" );
return(
<div>
<GetData/>
</div>
);
I suppose that problem is something about asynchronous, beacuse if I use some short list of data everthing is working great, but if I use this API and list of 250 object in list, sometimes data don't show up (and sometimes does). What am I doing wrong?
As you already said, data loading is asynchronous, so you must update loading
state variable inside the callback function :
componentDidMount(){
this.loadData(urlOfData, parameterToGet)
}
loadData(urlOfData, parameterToGet){
fetch(urlOfData)
.then(data => data.json())
.then(jsonData => {
// I didn't understand how you want to map the data
const data = jsonData.map(...);
console.log(data);
// you must update the state here
this.setState({loading: false, data: data});
});
}