Reputation: 57
I'm trying to make an API call that has for parameter a state set by another call :
I'll explain my code below !
import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
constructor(props) {
super(props);
this.state = {
coinList: [],
coinInfos: []
};
}
componentDidMount() {
// FIRST CALL HERE: I get a list of every coin
axios.get('https://min-api.cryptocompare.com/data/all/coinlist')
.then(res => {
const coins = res.data;
console.log(coins);
this.setState({ coinList: coins.Data });
});
// SECOND CALL HERE: I want to get the price of every coin of the previous list
if (this.state.coinList == null) {
return null;
}
else {
axios.get('https://min-api.cryptocompare.com/data/pricemultifull?fsyms=' + this.state.coinList + '&tsyms=USD')
.then(response => {
const coinCap = response.data;
this.setState({ coinInfos: coinCap.RAW });
});
}
render() {
return(
<div className="App">
{Object.keys(this.state.coinInfos).map((key) => (
<div className="container">
<span className="left">{key}</span>
<span className="right">{this.state.coinInfos[key].USD.MKTCAP}</span>
</div>
))}
</div>
);
}
}
I'm using an if condition for my second call because this.state.coinList
returns 2 empty arrays and 1 array in which are the data (I don't know why there are 2 empty arrays by the way).
This code works for the first call, but not for the second.
I'm a beginner in React so I looked at the doc, I think the problem is that the 1st call doesn't render before the second call, so this.state.coinList
is empty.
Can you tell me if I'm wrong ? And if I'm true, where should I make my second API call ?
I hope I'm clear, thank you for your time !
Here is the API's doc if you need : https://www.cryptocompare.com/api/#-api-data-
Upvotes: 0
Views: 2967
Reputation: 51
You are making asynchronous calls for operations you want to perform synchronously. Then First answer is correct but I would prefer to use async/await
// Put async before the componentDidMount so you can use async/await
async componentDidMount() {
// FIRST CALL HERE: I get a list of every coin
const resp1 = await axios.get(
"https://min-api.cryptocompare.com/data/all/coinlist"
);
const coins = resp1.data;
/* Placing the condition above the set state ensures
unnecessary setting of state and rending of components would not happen */
if (!coins) return;
this.setState({ coinList: coins });
// SECOND CALL HERE: I want to get the price of every coin of the previous list
const resp2 = axios.get(
`https://min-api.cryptocompare.com/data/pricemultifull?fsyms=${coins}&tsyms=USD`
);
this.setState({ coinInfos: resp2.data.RAW });
}
Upvotes: 0
Reputation: 3952
The calls are synchronous. You get to the second call before it even finishes the first one. As the simplest solution I would suggest to put the second call in the then
callback function of your first call.
In there you will have the response data of the first call for sure and then you can work with it and pass it to the second call.
componentDidMount() {
// FIRST CALL HERE: I get a list of every coin
axios.get('https://min-api.cryptocompare.com/data/all/coinlist')
.then(res => {
const coins = res.data;
console.log(coins);
this.setState({ coinList: coins.Data });
// SECOND CALL HERE: I want to get the price of every coin of the previous list
if (this.state.coinList == null) {
return null;
}
else {
axios.get('https://min-api.cryptocompare.com/data/pricemultifull?fsyms=' + this.state.coinList + '&tsyms=USD')
.then(response => {
const coinCap = response.data;
this.setState({ coinInfos: coinCap.RAW });
});
});
}
Upvotes: 2