I've simplified much of the code as the issue lies in the Promise and async/await part.
I wish for this ponent to get data from my API and create a plot from it. If the API is still retrieving, I want it to show the loading icon.
class Data extends Component {
state = {};
ponentDidMount() {
this.setState({ data: this.getData() });
}
async getData() {
try {
const response = await axios.get('/api/data');
return response.data;
} catch (err) {
return [];
}
}
renderLoading() {
return <Loading/>; // this represents a loading icon
}
renderPlot(data) {
return <Plot data={data}/>; // this represents the plot that needs the data
}
render() {
return {this.state.data
? this.renderLoading()
: this.renderPlot(this.state.data)};
}
}
At the moment, what this does is check this.state.data
, sees that it's undefined, and simply display the loading icon forever without ever checking it again. How can I make it recheck once the promise is pleted? One issue to note is that renderPlot requires data to be finished, if I call renderPlot while the Promise is still pending, it doesn't process it properly.
I've simplified much of the code as the issue lies in the Promise and async/await part.
I wish for this ponent to get data from my API and create a plot from it. If the API is still retrieving, I want it to show the loading icon.
class Data extends Component {
state = {};
ponentDidMount() {
this.setState({ data: this.getData() });
}
async getData() {
try {
const response = await axios.get('/api/data');
return response.data;
} catch (err) {
return [];
}
}
renderLoading() {
return <Loading/>; // this represents a loading icon
}
renderPlot(data) {
return <Plot data={data}/>; // this represents the plot that needs the data
}
render() {
return {this.state.data
? this.renderLoading()
: this.renderPlot(this.state.data)};
}
}
At the moment, what this does is check this.state.data
, sees that it's undefined, and simply display the loading icon forever without ever checking it again. How can I make it recheck once the promise is pleted? One issue to note is that renderPlot requires data to be finished, if I call renderPlot while the Promise is still pending, it doesn't process it properly.
2 Answers
Reset to default 7Instead of calling setState
before the data is ready, call this.getData()
in ponentDidMount
and then call setState
once the response data is ready. React will automatically re-render the ponent with state changes.
class Data extends Component {
state = {}
ponentDidMount() {
this.getData()
}
getData() {
axios
.get('/api/data')
.then(({ data }) => {
this.setState({ data })
})
.catch(err => {
this.setState({ error: err.message })
})
}
render() {
return this.state.data
? <Plot data={this.state.data} />
: this.state.error
? <div>{this.state.error}</div>
: <Loading />
}
}
You need to call setState after your async operation pletes. Try this in your ponentDidMount()
ponentDidMount() {
// Wait for the operation to plete before setting data
this.getData().then((d) => {
this.setState({ data: d});
});
}
Your code just sets data to be the Promise of the async operation.