We are creating a converter calculator based on React. Part 8: Currency Converter and Custom Data Parser


The epic with the calculator continues. This time we will add a currency converter to it, which collects exchange rate data from the banki.ru website in real time and provides information in the interface of our program.

All work will be divided into three steps – we will create a parser of the exchange rate from a third-party resource, a component for currency conversion and a switch for changing the data type for conversion.

Previous material: Calculator converter based on React. Part 7: Drag & Drop

We create a parser

A parser is a tool that allows you to collect data from a site and, if necessary, filter it to extract a specific piece of information from any page. Parsing can be used for various tasks. Checking the currency exchange rate is just one of the hundreds that are used in practice. You can parse almost any content from the network, where it is not prohibited by the owners of the sites and there is no special protection that prevents you from making requests through a normal browser.

To make your parser, you must first select a data source. In my opinion, the site banki.ru is quite suitable. I recommend using it, because the algorithm is configured specifically for this resource and may not work on other sites.

Banki.ru website

Before I started writing the parser code, I checked where exactly I would need to extract the data from. To do this, you need to open the information page and press the keys Shift+Ctrl+C. The developer tools will open and you can select any element on the page to view its code. I select the block named currency and see that it is a table component.

Developer tools in Google Chrome

The lack of explicit classes for name and amount complicates the task. It will be necessary to “generate crutches” and use artisanal methods to get to the necessary information.

HTML code on the page with currency rates

All of them are stored in single tr blocks, and this will allow us to set up a relatively simple algorithm for searching for the necessary content on banki.ru and its further use in the application. We are interested in the name of the currency and its value in relation to the ruble (at the moment this will be enough).

We configure axis and cheerio

If for some reason you missed setting up and installing Axios with Cheerio in the first step, you should do it now. Both utilities are necessary to get the necessary information about the page and then filter the necessary data.

Axios makes network requests and can provide the entire HTML code by link, and Cheerio is able to process this code by extracting specific components, targeting classes, attributes or simply the content of HTML blocks.

To install the first one, you need to enter the command:

npm install axios

To install the second:

npm install cheerio

It is not necessary to change the configuration files of these utilities. The default settings are fine for us.

We create a parser

The parser will be simple and fit into one function. We will write it in a separate parser.js file (you can place it anywhere convenient, and I will leave it in the src folder for now).

Inside parser.js will be the following code:

The code in the parser.js file

  • First, we import all the necessary elements, namely Cheerio and Axios (CommonJS syntax is used here, so instead of the usual imports, you will see the keyword require).

    const cheerio = require('cheerio), axios = require('axios')

  • Here we will note the link that the parser will refer to when trying to find information about the exchange rate.

    url = 'https://www.banki.ru/products/currency/cb/'

Next will be the code that is directly responsible for data mining. It is quite specific because it uses an array to store a block of information about a specific currency. I will try to explain its working principle as accessible as possible.

  1. We create an asynchronous getData function (this will be the main method for requesting information from banki.ru). The argument will be the word currency, through which it is planned to transfer the name of the currency.

    const getData = (currency) => { }

  2. We will create an empty array in the body of the function. In the future, it will contain all information about the selected currency.

    const array = []

  3. Then we create a response variable containing an asynchronous request to the banki.ru website via Axios.

    const response = await axios.get(url)

  4. Then we create a $ variable and add an asynchronous request to the Axios response from Cheerio to load the entire HTML code into the parser.

    const $ = await cheerio.load(response.data)

  5. The next step is to create a regular expression to search for the name of the exchange rate among all those listed on the banki.ru website. In our case, we only need to find the name of the specific currency passed to the getData function as an argument. That is, the regular expression will be the word currency.

    const regex = new RegExp(currency)

  6. Now you can use Cheerio. First, we’ll load the entire list of tr elements into the parser and start traversal. Using the each method, we will refer to all elements with the tr tag. If the name of the selected currency is found in the text of at least one of them (if test), then we will add the entire HTML code of this tr-block to our array.

    $('tr').each((e, i) => {if ($(i).text().match(regex)) {$(i).children().each((e, x) => array.push($(x).html()))} })

  7. At the end of the getData function, we will return the third element of the array. Why the third? Because this is the amount listed next to the currency name.

    return array[3]

After that, you need to export the getData method:

Export method getData

And then import it, but already in the converter.

Import the getData method

The community is now in Telegram

Subscribe and stay up to date with the latest IT news

Sign up

New currency conversion component

Currency conversion will (for now) require a separate component. For this, we will not go far, but copy the code that we already have. That is, the one used to convert meters to centimeters.

Converter component code

We’ll take the same code and extract it into a separate component. Let’s call it Money for now. The main thing is not to forget to rename the basic units. In our case, it is “US Dollar” and “Rubles”. You need to replace the internal text with option and value with option.

And note that the references are now passed as props, because we have extracted the existing logic into a separate component. Accordingly, all methods and elements associated with the parent component must now be passed as props.

Changed the code of the Money component

Currency conversion method

Additional converter logic (not related to parsing) is written in the converter component. Until we’ve extracted all the formulas into separate functions and files, let’s create a new method right inside Converter and call it convertMoney. This will be an asynchronous function of calculating the exchange rate based on information from the parser.

function convertMoney

  • We declare the method itself.

    async function convertMoney() { }

  • In its body, we make an asynchronous request to the getData function and pass the value of the first reference as an argument (references are written in the seventh part of the cycle). For example, it will be “US Dollar”.


  • If the request is successful, we will call the switch construct, which will check the currency in the second reference and make a calculation based on it. Let’s change the value of the result state:x => { case 'Рубли': setResult(input * Number(x)); break }

It should be noted here that we are casting (data type conversion) the value of x to Number because by default the getData method returns a string and not a number. This behavior can be avoided by adding casts directly inside getData. Then you won’t have to write extra code in convertMoney. See as it is more convenient for you.

done We have a parser, a rate calculation method, and even a primitive interface to track the performance of the converter. The only problem is that it is not connected to the Converter component. But we will fix it.

We create a menu for switching between different converters

We have already made a drop-down menu in previous parts when it was necessary to create a switch between a calculator and a converter. Now we need another similar switch, but for different types of converters. In order not to pile up all types of metrics (and there can be a lot of them), it is better to separate them into separate menus.

To begin with, let’s create a Menu component in the Converter.jsx file and completely copy the code there from the Menu located in the App.jsx file.

The Menu component in the converter

Only in this component we will replace the names of the switches. Instead of Calculator and Converter, let’s make Money and Distance.

Buttons for switching conversion modes

Next, you need to supplement the Converter component code with all the elements that are responsible for switching the program’s operating modes. First, we create the mode state and equate it to Distance by default:

const [mode, setMode] = useState('Distance')

Mode state in the Converter component

Then we create a converter variable in which the component will be stored for display in the interface:

let converter

And we add the switch construction, which is responsible for the mode of operation of the currently displayed converter:

Switch construction for switching types of conversion

Using the example of Money, we will analyze the props transferred to the new type of components:

  1. setInput is a method of changing the value of the Input field inside the Converter component.

  2. convert – Conversion method. As for Money, it’s convertMoney, because the conversion method is different from the one used when converting distances.

  3. first and second are references to two Select fields.

  4. data is an array with a list of items to be displayed in the Select menu. We will talk about this below.

The converter variable in the return method

Now, instead of separate Money or Distance components, we can send the converter variable to the return method, and it will decide which type of converter is available to the user. You won’t have to fence dozens of conversions on one page.

We simplify the reuse of components

Now let’s talk in more detail about what data is and why this variable appeared at all in the list of props belonging to components with converters.

data is an array, which by design should contain information about the metrics that will be calculated inside the converter. Thanks to separate arrays with a list of these values, you can refuse to manually enter option blocks in each component. That is, exclude the following lines from the Money code:

<option value="Доллар США">Доллар США</option>

Array data

Instead, we will create an array with all possible values ​​for conversion and pass its component as props.

Money component with data props

After that, it will be possible to process the props inside the component and allocate each element of the array in the Select block so that it is displayed as a block

To implement this, let’s create a selection variable and write a data array sorting function.

const selection = props.data.map(e => {return <option key={e} value={e}>{e}</option>})

And the resulting variable is sent to the code between the Select tags.

<Select ref={props.first}> {selection} </Select>

Money component

This approach will simplify the re-creation and use of components, as it will not be necessary to re-specify the entire list of elements to be converted in one data block.

Data arrays

In the same way, you can create data arrays for an unlimited number of metrics and generally display them in a separate file so that they do not interfere with the main logic of the component.

But that’s not all, because we have to create a new component with a lot of repeating logic for each kind of metrics. This slows down the development process and makes the code too bulky and inconvenient to edit. Therefore, it is necessary to turn the component with Select blocks into something more universal.

We’ll keep the same code in it, but rename the component itself to Convertible to reflect its new entity. It is now responsible for all kinds of metrics.

Universal component

All we have to do is pass various props to this component. Different calculation methods, different arrays with lists of metrics, etc.

Updated switch design

If we want to change the design or logic with the list of elements

And finally, here is a scary picture with two dollars converted into rubles.

Currency converter interface

Instead of imprisonment

Now you know how to create your own parser based on Axios and Cheerio, know how to filter data, and decompose the interface into the simplest form so that you can easily edit and add to it.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

© 2022 ZoNa365.ru - Theme by WPEnjoy · Powered by WordPress