Reputation: 831
I am doing currency calculator with react.js
fetching current rates to state by getRates function:
getRates(currencyShortcut){
fetch('https://api.fixer.io/latest?base='+currencyShortcut)
.then(response => response.json())
.then(parsedJson => this.setState({currencyRates:parsedJson}))
.catch(error => console.log('fetch error - ', error))
}
and I use them to calculate amount for given input value, which is displayed on screen here is how:
calculateCurrenciesValues(curr,userInput){
let currency1val,currency2val;
const rate = this.state.currencyRates.rates[this.state.currency2.shortcut];
if(curr === 1){
currency1val = userInput;
currency2val = Math.round(rate*userInput*100)/100;
}else{
currency1val = Math.round(userInput/rate*100)/100;
currency2val = userInput;
}
this.setState({
currenciesValues:[currency1val,currency2val]
})
}
first HTTP request is done with componentWillMount
componentWillMount(){
this.getRates('USD');
}
but you can also select another currency from list and than state needs to get new rates, so here is handler for currency changing:
changeCurrency(currFlag,currShortcut,currSymbol){
const selectedCurrency = {
path:currFlag,
shortcut:currShortcut,
symbol:currSymbol
};
const {listOfCurrencies,currency1,currency2,currenciesValues,currencyRates} = this.state;
if(this.state.listOfCurrencies.displayFor === 1 ){
this.getRates(currShortcut);
this.setState({
currency1:selectedCurrency
})
this.calculateCurrenciesValues(1,currenciesValues[0])
}
else{
this.setState({
currency2:selectedCurrency
});
this.calculateCurrenciesValues(2,currenciesValues[1])
}
this.setState({
listOfCurrencies:{
display:!listOfCurrencies.display
}
})
}
As you can see, what I am trying to do is recalculation after currency is changed and although this.getRates(currShortcut) loads new rates for state, calculation this.calculateCurrenciesValues(1,currenciesValues[0]) is done on old rates not fresh ones, as I would expect.
In practice, it looks as follows e.g. I got choosen USD => GBP for default and I enter 10 in first input and get displayed "10$ = 7.06£", so I want something else for USD so I change it for EUR and I got EUR => GBP than I get new rates in state, but calculation is done with old rates so only currency sign changes in displayed values "10€ = 7.06£" and if I am going to change currency for second time lets make it JPY now, there are new rates in state but again calculation is done with old rates, which were correct for EUR "10¥ = 8.79£"
Anybody got an idea, how to make calculation with freshly acquired data?
Upvotes: 1
Views: 723
Reputation: 103
Your ajax request must be done before you call a method. You can try this
getRates(currencyShortcut, callback){
fetch('https://api.fixer.io/latest?base='+currencyShortcut)
.then(response => response.json())
.then(parsedJson => this.setState({currencyRates:parsedJson}, function(){if(callback){callback();})
.catch(error => console.log('fetch error - ', error))
}
if(this.state.listOfCurrencies.displayFor === 1 ){
this.getRates(currShortcut, function(){
this.setState({
currency1:selectedCurrency
}, function(){
this.calculateCurrenciesValues(1,currenciesValues[0])
})
});
}
Upvotes: 0
Reputation: 4497
If your calculateCurrenciesValues() is using an incorrect value, I would first guess you are setting state and calling functions in the wrong order.
I would approach it as follows...
User changes the currency
Event fires where function runs to calculate new value based on the current state (which reflects the current user input)
Sounds like you may be handling events out of order. Look into your code to make sure your state is first being updated to reflect the current user input and base your calculations on that current state. Hope this helps, sorry if not.
Upvotes: 0
Reputation: 9812
Try to store in the state only the rates and the current user selections.
Perform the calculation in your render method, this way it will rerun whenever the state changes.
Upvotes: 4