Build a Dynamic React JS Interactive Simple Interactive Component: Currency Converter

In today’s interconnected world, the need to convert currencies is a frequent occurrence. Whether you’re planning a trip abroad, managing international finances, or simply curious about exchange rates, having a reliable currency converter at your fingertips is incredibly useful. This tutorial will guide you through building a dynamic and interactive currency converter using React JS, a popular JavaScript library for building user interfaces. We’ll break down the process step-by-step, making it easy for beginners to understand and implement.

Why Build a Currency Converter with React?

React offers several advantages for building interactive web applications like a currency converter:

  • Component-Based Architecture: React’s component-based structure allows you to break down the converter into smaller, manageable pieces (input fields, dropdowns, result display), making the code organized and reusable.
  • Virtual DOM: React uses a virtual DOM to efficiently update the actual DOM, leading to faster and smoother user interactions. This is especially important for applications that need to update frequently, like a currency converter that shows real-time exchange rates.
  • State Management: React’s state management capabilities make it easy to manage the data that drives your application, such as the amounts being converted, the selected currencies, and the calculated results.
  • Rich Ecosystem: React has a vast ecosystem of libraries and tools that can simplify development. For example, you can easily integrate APIs to fetch real-time exchange rates.

Prerequisites

Before we begin, make sure you have the following:

  • Node.js and npm (or yarn) installed: These are essential for managing JavaScript packages and running React applications. You can download them from nodejs.org.
  • A basic understanding of HTML, CSS, and JavaScript: While this tutorial aims to be beginner-friendly, familiarity with these web technologies is helpful.
  • A code editor: Choose your favorite code editor (e.g., VS Code, Sublime Text, Atom) to write and edit your code.

Setting Up the React Project

Let’s start by creating a new React project using Create React App, a popular tool that sets up a React development environment for you. Open your terminal or command prompt and run the following command:

npx create-react-app currency-converter
cd currency-converter

This command creates a new directory named “currency-converter” and sets up a basic React application inside it. Then, it navigates into the created directory. Now, start the development server:

npm start

This will open your application in your default web browser, usually at http://localhost:3000. You should see the default React welcome screen.

Project Structure Overview

Before diving into the code, let’s take a quick look at the project structure created by Create React App:

  • src/: This directory is where you’ll write your React code.
  • src/App.js: This is the main component of your application, where we’ll build the currency converter.
  • src/App.css: This file contains the CSS styles for your application.
  • public/: This directory contains static assets like the HTML file and images.
  • package.json: This file lists the dependencies of your project.

Building the Currency Converter Component

Now, let’s start building the currency converter component. Open `src/App.js` in your code editor. We’ll replace the existing content with our own code.

First, we’ll create the basic structure, including input fields for the amount, dropdowns for selecting currencies, and a display area for the converted amount. We’ll also add some basic styling in `src/App.css` to make it visually appealing. Here’s the code for `src/App.js`:

import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  // State variables
  const [amount, setAmount] = useState(1);
  const [fromCurrency, setFromCurrency] = useState('USD');
  const [toCurrency, setToCurrency] = useState('EUR');
  const [exchangeRate, setExchangeRate] = useState(null);
  const [convertedAmount, setConvertedAmount] = useState(null);
  const [currencyOptions, setCurrencyOptions] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  // API key (replace with your own)
  const apiKey = 'YOUR_API_KEY';

  useEffect(() => {
    const fetchCurrencies = async () => {
      setIsLoading(true);
      try {
        const response = await fetch('https://api.exchangerate-api.com/v4/latest/USD'); // You can use any base currency
        if (!response.ok) {
          throw new Error('Failed to fetch currency data');
        }
        const data = await response.json();
        // Extract currencies from the response
        const currencies = Object.keys(data.rates);
        setCurrencyOptions(currencies);
      } catch (error) {
        setError(error.message);
      } finally {
        setIsLoading(false);
      }
    };

    fetchCurrencies();
  }, []);

  useEffect(() => {
    const fetchExchangeRate = async () => {
      if (!fromCurrency || !toCurrency) return;
      setIsLoading(true);
      setError(null);
      try {
        const response = await fetch(
          `https://api.exchangerate-api.com/v4/latest/${fromCurrency}` // Use your API endpoint
        );
        if (!response.ok) {
          throw new Error('Failed to fetch exchange rate');
        }
        const data = await response.json();
        const rate = data.rates[toCurrency];
        setExchangeRate(rate);
        setConvertedAmount(amount * rate);
      } catch (error) {
        setError(error.message);
      } finally {
        setIsLoading(false);
      }
    };

    fetchExchangeRate();
  }, [amount, fromCurrency, toCurrency]);

  const handleAmountChange = (e) => {
    setAmount(e.target.value);
  };

  const handleFromCurrencyChange = (e) => {
    setFromCurrency(e.target.value);
  };

  const handleToCurrencyChange = (e) => {
    setToCurrency(e.target.value);
  };

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  return (
    <div>
      <h1>Currency Converter</h1>
      <div>
        <div>
          <label>Amount:</label>
          
        </div>
        <div>
          <div>
            <label>From:</label>
            
              {currencyOptions.map((currency) => (
                
                  {currency}
                
              ))}
            
          </div>
          <div>
            <label>To:</label>
            
              {currencyOptions.map((currency) => (
                
                  {currency}
                
              ))}
            
          </div>
        </div>
        <div>
          {convertedAmount !== null && (
            <p>
              {amount} {fromCurrency} = {convertedAmount.toFixed(2)} {toCurrency}
            </p>
          )}
        </div>
      </div>
    </div>
  );
}

export default App;

And here’s the code for `src/App.css`:

.app {
  font-family: sans-serif;
  text-align: center;
  padding: 20px;
}

.converter-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #f4f4f4;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  width: 80%;
  max-width: 500px;
  margin: 0 auto;
}

.input-group {
  margin-bottom: 15px;
}

label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
}

input[type="number"],
select {
  padding: 10px;
  font-size: 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
  width: 100%;
  margin-bottom: 10px;
}

.currency-group {
  display: flex;
  justify-content: space-between;
  width: 100%;
  margin-bottom: 15px;
}

.from-currency, .to-currency {
  width: 48%; /* Adjust as needed */
}

.result {
  font-size: 1.2em;
  font-weight: bold;
}

.loading {
  text-align: center;
  font-size: 1.2em;
  margin-top: 20px;
}

.error {
  color: red;
  text-align: center;
  font-size: 1.2em;
  margin-top: 20px;
}

In this code, we have:

  • State Variables: We use the `useState` hook to manage the following states: `amount`, `fromCurrency`, `toCurrency`, `exchangeRate`, `convertedAmount`, `currencyOptions`, `isLoading`, and `error`.
  • Input Fields: We have an input field (`<input type=”number”>`) for the amount to be converted.
  • Dropdowns: We use `<select>` elements to allow the user to choose the currencies for conversion.
  • Result Display: A `<p>` element displays the converted amount.
  • Event Handlers: We have `handleAmountChange`, `handleFromCurrencyChange`, and `handleToCurrencyChange` functions to update the state when the user interacts with the input fields and dropdowns.

Fetching Exchange Rates from an API

The core functionality of the currency converter is fetching real-time exchange rates from an API. We’ll use the `useEffect` hook to make API calls when the component mounts and when the `fromCurrency`, `toCurrency`, or `amount` changes. For this tutorial, we will be using the free API from exchangerate-api.com.

First, you will need to get an API key from exchangerate-api.com. Once you have the key, replace “YOUR_API_KEY” in the code above with your actual API key. If you are using the free plan, you don’t need an API key, so you can remove the apiKey variable. The free plan has limitations, so consider using a paid plan if you need higher limits or more features. Here’s how to fetch the exchange rates:

  useEffect(() => {
    const fetchExchangeRate = async () => {
      if (!fromCurrency || !toCurrency) return;
      setIsLoading(true);
      setError(null);
      try {
        const response = await fetch(
          `https://api.exchangerate-api.com/v4/latest/${fromCurrency}` // Use your API endpoint
        );
        if (!response.ok) {
          throw new Error('Failed to fetch exchange rate');
        }
        const data = await response.json();
        const rate = data.rates[toCurrency];
        setExchangeRate(rate);
        setConvertedAmount(amount * rate);
      } catch (error) {
        setError(error.message);
      } finally {
        setIsLoading(false);
      }
    };

    fetchExchangeRate();
  }, [amount, fromCurrency, toCurrency]);

In this code:

  • We use the `useEffect` hook with `[amount, fromCurrency, toCurrency]` as dependencies. This means the effect will run whenever these values change.
  • We use the `fetch` API to make a request to the exchange rate API.
  • We parse the JSON response.
  • We extract the exchange rate from the response data.
  • We calculate the converted amount and update the state.
  • We handle potential errors using `try…catch` blocks and update the `error` state.
  • We use `setIsLoading` to show a loading indicator while the API request is in progress.

Fetching Available Currencies

To populate the dropdowns with available currencies, we need to fetch a list of currencies from an API. We’ll create another `useEffect` hook to do this when the component mounts. We will use the same API as before, but a different endpoint to get a list of supported currencies.


  useEffect(() => {
    const fetchCurrencies = async () => {
      setIsLoading(true);
      try {
        const response = await fetch('https://api.exchangerate-api.com/v4/latest/USD'); // You can use any base currency
        if (!response.ok) {
          throw new Error('Failed to fetch currency data');
        }
        const data = await response.json();
        // Extract currencies from the response
        const currencies = Object.keys(data.rates);
        setCurrencyOptions(currencies);
      } catch (error) {
        setError(error.message);
      } finally {
        setIsLoading(false);
      }
    };

    fetchCurrencies();
  }, []);

In this code:

  • We use the `useEffect` hook with an empty dependency array (`[]`). This means the effect will run only once when the component mounts.
  • We fetch the currency data from the API.
  • We extract the currency codes from the response.
  • We update the `currencyOptions` state with the fetched currency codes.
  • We handle potential errors using `try…catch` blocks.
  • We use `setIsLoading` to show a loading indicator.

Handling User Input

We need to handle user input for the amount and the selected currencies. We’ll use event handlers to update the state when the user changes the input fields and dropdowns.


  const handleAmountChange = (e) => {
    setAmount(e.target.value);
  };

  const handleFromCurrencyChange = (e) => {
    setFromCurrency(e.target.value);
  };

  const handleToCurrencyChange = (e) => {
    setToCurrency(e.target.value);
  };

These functions update the `amount`, `fromCurrency`, and `toCurrency` states based on the user’s input.

Displaying the Converted Amount

Finally, we display the converted amount in the `<div className=”result”>` section. We check if `convertedAmount` is not null before displaying it.


  <div className="result">
    {convertedAmount !== null && (
      <p>
        {amount} {fromCurrency} = {convertedAmount.toFixed(2)} {toCurrency}
      </p>
    )}
  </div>

We use `toFixed(2)` to format the converted amount to two decimal places.

Common Mistakes and How to Fix Them

Here are some common mistakes developers make when building currency converters and how to avoid them:

  • Not Handling API Errors: Always handle potential errors from the API by using `try…catch` blocks and displaying an error message to the user.
  • Incorrect API Endpoint: Double-check the API endpoint and ensure it’s correct. Typos can easily lead to errors.
  • Missing API Key: If the API requires an API key, make sure you’ve included it in your request.
  • Not Updating State Correctly: Make sure you’re correctly updating the state variables using the `useState` hook. Incorrect state updates can lead to unexpected behavior.
  • Not Handling Edge Cases: Consider edge cases like invalid input or very large numbers. You might want to add input validation to prevent unexpected behavior.

Step-by-Step Instructions

Here’s a step-by-step guide to building your currency converter:

  1. Set Up the Project: Create a new React app using `create-react-app`.
  2. Create the Component Structure: Define the basic structure of your currency converter with input fields, dropdowns, and a result display.
  3. Fetch Currency Options: Use `useEffect` to fetch a list of available currencies from an API and populate the dropdowns.
  4. Fetch Exchange Rates: Use `useEffect` to fetch the exchange rate based on the selected currencies and the amount entered by the user.
  5. Handle User Input: Use event handlers to update the state when the user interacts with the input fields and dropdowns.
  6. Display the Converted Amount: Display the converted amount in the result section.
  7. Add Styling: Add CSS styles to make the converter visually appealing.
  8. Test and Debug: Thoroughly test your converter and debug any issues that arise.

Key Takeaways

In this tutorial, we’ve covered the essential steps to build a dynamic currency converter with React:

  • Component Structure: We used a component-based approach to structure the application.
  • State Management: We utilized the `useState` hook to manage the state of the application.
  • API Integration: We integrated with an API to fetch real-time exchange rates.
  • User Interaction: We handled user input to provide an interactive experience.

FAQ

Here are some frequently asked questions about building a currency converter in React:

  1. How can I handle API errors? You can use `try…catch` blocks to handle API errors and display an error message to the user.
  2. How can I add more currencies? You can add more currencies by updating the API endpoint to include the desired currencies and updating the `currencyOptions` state.
  3. How can I improve the user interface? You can improve the user interface by adding more styling, using a UI library (like Material UI or Ant Design), and adding features like currency symbols and a history of conversions.
  4. How can I deploy this application? You can deploy your React application to platforms like Netlify, Vercel, or GitHub Pages.
  5. Can I use a different API? Yes, there are many free and paid APIs available. You can choose an API that meets your needs and replace the API endpoint in the code.

Building a currency converter with React is a great way to learn about React’s core concepts, including components, state management, and API integration. By following this tutorial, you’ve gained the skills to create a useful and interactive web application. With the knowledge you’ve gained, you can now explore more advanced features, experiment with different APIs, and customize the converter to meet your specific needs. Remember to always handle errors, test your code thoroughly, and consider user experience when building your application. Continuous learning and experimentation are key to becoming a proficient React developer. The world of front-end development is constantly evolving, so embrace the opportunity to explore new technologies and refine your skills. You’ve now taken your first steps into building a practical and valuable tool, opening up a world of possibilities for your front-end development journey.