Reputation: 505
I'm creating just a simple currency converter (React + Typescript). Here is my component code:
const App = () => {
const [countries, setCountries] = useState<Array<CountriesProps>>([])
const [currencies, setCurrencies] = useState<Currencies>({})
const filteredCountries = async () => {
const { data } = await axios.get('https://restcountries.eu/rest/v2/all')
const answer: Array<CountriesProps> = data
const filtered = answer.filter(country => {
for (let i in currencies) {
if(i === country.currencies[0].code) {
return country
}
}
})
setCountries(filtered)
}
useEffect(() => {
axios
.get('https://api.frankfurter.app/currencies')
.then(res => {
setCurrencies(res.data)
})
.catch(err => {
console.log(err)
})
}, [])
useEffect(() => {
filteredCountries()
}, [])
return (
...
)
}
export default App
I come across the problem, during launching the app. After getting currencies information from the server I need to fetch countries information. After getting countries I need to filter them and put them in my state (countries) and send it to another component and so on. But during launch of the app filter function doesn't work and I got no filtered countries and so I don't have any info in my state. I think that filter function needs to be an asynchronous, so we need to wait before setting our state through setCountries function. How to do it properly in my case or I did all the logic wrong?
Upvotes: 0
Views: 1364
Reputation: 15530
As long as requested countries rely on fetched currencies and you don't seem to be using one without the another, you may stack .get()
-requests accordingly or use respective async...await
alternative:
fetchData = async () => {
const currenciesResponse = await axios.get(currenciesEndpoint),
currenciesData = await currenciesResponse.data,
countriesResponse = await axios.get(countriesEndpoint),
countriesData = await countriesResponse.data,
filteredCountriesData = countriesData.filter(_country => {
const {
currencies: [{ code }]
} = _country;
return currenciesData[code];
});
setCurrencies(currenciesData);
setCountries(filteredCountriesData);
}
useEffect(() => {
fetchData();
}, [])
Following is a full-blown demo as a proof-of-a-concept
Upvotes: 1
Reputation: 6582
try using this:
const App = () => {
const [countries, setCountries] = useState<Array<CountriesProps>>([])
const [currencies, setCurrencies] = useState<Currencies>({})
const filteredCountries = async () => {
const res = await axios.get('https://api.frankfurter.app/currencies')
// you don't need a state for currencies but in case you find a use case for it,
// you're just setting the currencies here for future use cases.
setCurrencies(res.data);
const { data } = await axios.get('https://restcountries.eu/rest/v2/all')
const answer: Array<CountriesProps> = data
const filtered = answer.filter(country => {
for (let i in res.data) {
if(i === country.currencies[0].code) {
return country
}
}
})
setCountries(filtered)
}
useEffect(() => {
filteredCountries()
}, [])
return (
...
)
}
export default App
Upvotes: 0
Reputation: 3317
See if this helps.
const [countries, setCountries] = useState<Array<CountriesProps>>([])
const [currencies, setCurrencies] = useState<Currencies>({})
const filteredCountries = async () => {
const { data } = await axios.get('https://restcountries.eu/rest/v2/all')
const answer: Array<CountriesProps> = data
const filtered = answer.filter(country => {
return currencies[country.currencies[0].code]
})
setCountries(filtered)
}
useEffect(() => {
axios
.get('https://api.frankfurter.app/currencies')
.then(res => {
setCurrencies(res.data)
})
.catch(err => {
console.log(err)
})
}, [])
useEffect(() => {
filteredCountries()
}, [currencies])
Upvotes: 0