Tips for ensuring synchronous state changes in React

I am working on a currency calculator using react.js

I am fetching the latest exchange rates and storing them in state using the 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))   
 }

These rates are then used to calculate the amount for a given input value, which is displayed on the screen as shown below:

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]
  })
}

The initial HTTP request is made within the componentWillMount method

componentWillMount(){
    this.getRates('USD');
}

If a user selects a different currency from the list, the state needs to be updated with new rates. Here is the handler for changing the currency:

  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
      }
    })
  }

After changing the currency, the calculation should ideally be done with the freshly acquired data. However, I am facing an issue where the calculation is not updating with the new rates after changing the currency.

Any suggestions on how to ensure that the calculation uses the most up-to-date exchange rates?

Answer №1

Consider saving only the exchange rates and user selections in the state.

Calculate values within your render method to ensure it updates whenever the state is modified.

Answer №2

If your calculateCurrenciesValues() function is producing incorrect results, the issue may be related to the order in which you are setting state and calling functions.

Here's how I would tackle it...

  • User inputs a value into the field
  • An onChange event occurs to update the state with the current input value
  • The user changes the currency selection
  • An event triggers the function to calculate a new value based on the current state representing the user input

It seems like there could be a problem with the sequence of events in your code. Double check that your state is updated before performing calculations based on the current user input. Hopefully, this will provide some clarity. If not, feel free to reach out for further assistance.

Answer №3

Make sure to complete your ajax request before calling a method. Here's a suggested approach:

fetchCurrencyRates(shortcut, callback){
     fetch('https://api.fixer.io/latest?base='+shortcut)
       .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.fetchCurrencyRates(shortcut, function(){
      this.setState({
        currency1:selectedCurrency
      }, function(){
        this.calculateCurrenciesValues(1,currenciesValues[0])
      })
  });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing AJAX POST requests from JavaScript to a Rails 4 controller while implementing Strong Parameters

As a newcomer to Rails, I am looking to insert song_id and title received from JavaScript via AJAX POST into a MySQL database. In my JavaScript file: var song_id = "23f4"; var title = "test"; $( document ).ready( function() { jQuery.ajax({ ...

Implementing the Upload Feature using AngularJS

Currently, I'm facing a challenge in implementing an upload button on my webpage using AngularJS and Bootstrap. Specifically, I am having trouble assigning the (upload) function to that button in AngularJS. The goal is for the button to enable users t ...

The Ultimate Guide to Automatically Updating JSON File URLs

I am currently working on a project where I need to retrieve data from a URL using the $.getJSON method. I am interested in finding a way to continuously update this data and replace it in the HTML without needing to manually refresh the page. Although I h ...

Guide on embedding PHP code into a HTML div element using JQuery

I am having trouble loading PHP code into a div tag to display the results. The code I have listed below does not seem to work for me. If anyone can offer assistance in resolving this issue, I would greatly appreciate it. Here is the code snippet: <h ...

employing document.write() specifically for a designated division

This is the coding: $(document).ready(function(){ var Jstr = { "JSON" : [ { "Eid" : 102,"Ename":"", "Ecode" : "<input type ='text'/>", "Eprops": {"name": "", "value":"", "maxlength":""}} ] } ; $(".search").click(funct ...

Using HTML and C# to Deliver Emails

I've encountered a challenge with my HTML page that includes a textbox for users to input their email. When the submit button is clicked, an email should be sent to a specific email address defined in the code, and a pop-up box indicating "Email Sent" ...

Issue with rendering HTML tags when replacing strings within Ionic 2 and Angular 2

I am currently working with an array of content in my JSON that includes URLs as plain text. My goal is to detect these text URLs and convert them into actual clickable links. However, I'm facing an issue where even though the URL is properly replaced ...

The updates made to a form selection using Ajax do not reflect in jQuery's .serialize or .val functions

When using the .load jQuery function to retrieve a form and place it in the document body, I encounter an issue. After loading the form, I manually change the select value and attempt to save the form using an ajax .post request. However, when trying to ...

What is the term used to describe the way console.log styles the Json object?

Have you ever noticed that when a JSON object is printed, say in a script run by node using console.log, it doesn't exactly pretty print the JSON? It sort of strikes a balance between showing as few lines as possible while still maintaining readabilit ...

Sending a function as a callback to children components in order to update a specific child component

I am currently working on developing a Navbar component that undergoes slight changes when a user logs in through a SignIn component. Here is an overview of how my application is structured: Initially, I have defined a state in the App component where aut ...

Tips for creating text that adjusts to the size of a div element

I'm currently working on developing my e-commerce website. Each product is showcased in its own separate div, but I've encountered a challenge. The issue arises when the product description exceeds the limits of the div, causing it to overflow ou ...

Prevent textArea from reducing empty spaces

I am facing an issue with my TextEdit application set to Plain Text mode. When I copy and paste text from TextEdit into a textarea within an HTML form, the multiple spaces get shrunk. How can I prevent the textarea from altering the spacing in the text? T ...

A chart using JavaScript that displays text values instead of a traditional website

I am a student with no background in programming, however, for my project I need to create a chart based on values from a txt file to display sensor data. I came across a chart that retrieves its values from a website, but I would like to modify it so it c ...

Import several image files using AngularJS

I recently came across a helpful tutorial that demonstrates how to upload pictures from your local computer using AngularJS directives. As a newcomer to Angular, I followed the instructions but now I'm stuck on modifying it to display the selected ima ...

Developing a trivia game using HTML and JavaScript

I'm in need of some serious assistance with creating a quiz using HTML. My goal is to have a web page where users can visit, take a quiz, and have their responses stored. Unfortunately, I don't have the knowledge or skills required to do this on ...

Tips for managing the onloadedmetadata event

If a video file cannot be played by the browser due to format or codec issues, I want to notify the user about it. When the browser is unable to play a video (because of unsupported format or codec), the onloadedmetadata event does not occur. I have some ...

Discover the power of integrating JSON and HTTP Request in the Play Framework

My aim is to develop a methodology that can effectively manage JSON and HTTP requests. This approach will facilitate the transition to creating both a Webapp and a Mobile App in the future, as JSON handling is crucial for processing requests across differe ...

Tips on maintaining and hiding the vertical scrollbar when a popup is open, alongside the navigation bar positioned at the top of the page

After reviewing this pen, my goal is to create a popup that maintains access to the navigation bar (hence avoiding Bootstrap's Modal). However, I am facing the challenge of keeping the scrollbar visible while preventing scrolling in the background whe ...

Is it possible to eliminate the array from a property using TypeScript?

Presenting my current model: export interface SizeAndColors { size: string; color: string; }[]; In addition to the above, I also have another model where I require the SizeAndColors interface but without an array. export interface Cart { options: ...

The conditional statement in the given code snippet is failing to execute properly

const checkCondition = (props) => { let conditionMet = false; console.log('-----****----',props); if(props && props.isAllowed) { conditionMet = true; } if(someOtherCondition) { return( <li><Link className=" ...