Story: Building the Currency Converter App

1. The Beginning: The User Interaction in the UI

Imagine you’ve just opened the currency converter app. You see two sections: one where you can enter the amount you want to convert, and the other where the converted amount will appear. There are also two dropdowns, one for selecting the currency you are converting from (e.g., USD) and another for selecting the currency you want to convert to (e.g., INR).

To make everything work, we need to:

  • Capture the amount entered by the user.

  • Store the selected currencies (from and to).

  • Calculate the converted amount based on the rates.

These steps involve React components, state management, API fetching, and event handling.


2. Setting Up the State in App.jsx (The Central Brain)

import { useState } from 'react';
import './App.css';
import { InputBox } from './components';
import useCurrencyInfo from './hooks/useCurrencyInfo';

// The `App` component is the main brain of our app
function App() {
  const [amount, setAmount] = useState(0); // Amount user wants to convert
  const [from, setFrom] = useState("usd"); // Currency user wants to convert from (USD by default)
  const [to, setTo] = useState("inr"); // Currency user wants to convert to (INR by default)
  const [convertAmount, setConvertAmount] = useState(0); // Converted amount

  // This hook fetches the currency conversion data based on the "from" currency
  const currencyInfo = useCurrencyInfo(from);

  // Options are the keys of the currencyInfo object
  const options = Object.keys(currencyInfo);

At the start, App.jsx is the starting point. It holds the state values, which are like storage containers that hold important information for the app:

  • amount: The amount you want to convert (e.g., 10 USD).

  • from: The currency you are converting from (USD by default).

  • to: The currency you are converting to (INR by default).

  • convertAmount: This will hold the converted amount after the calculation.

React’s useState hook is used to store these values. Think of it like a memory bank where we store the user inputs and the results.


3. Fetching the Currency Data with useCurrencyInfo (Gathering Data)

Next, we need to fetch the conversion rates from an external API. This is where the useCurrencyInfo hook comes in.

import { useEffect, useState } from "react";

// Custom hook to fetch currency information
const useCurrencyInfo = (currency) => {
  const [currencyData, setCurrencyData] = useState({});

  useEffect(() => {
    const fetchCurrencyData = async () => {
      try {
        const response = await fetch(`https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/${currency}.json`);
        const data = await response.json();
        setCurrencyData(data[currency]);
      } catch (error) {
        console.error("Error fetching currency data:", error);
      }
    };

    fetchCurrencyData();
  }, [currency]); // This effect runs whenever the "currency" changes

  return currencyData;
};

Here’s what happens:

  • useEffect: This is like a listener that waits for the from currency to change. If the from currency changes (e.g., from USD to EUR), it will fetch the new conversion rates for the selected currency.

  • fetchCurrencyData: This is an asynchronous function that calls an API to get the current conversion rates for the selected currency.

    • For example, if the user selects USD, it fetches the exchange rates for USD in relation to other currencies, like INR, EUR, etc.
  • setCurrencyData: Once the data is fetched, it's stored in the currencyData state, which is returned by the hook.

This means that whenever the user selects a new "from" currency, the app will fetch the latest conversion rates.


4. Showing the Data: The InputBox Component

The InputBox component is where the magic happens. It lets the user enter the amount they want to convert and select the currency from a dropdown.

const InputBox = ({ label, amount, CurrencyOptions, onCurrencyChange, onAmountChange, selectCurremcy, amountDisable }) => {
  return (
    <div className="w-full">
      <label className="block text-sm font-medium text-gray-700">{label}</label>
      <input
        type="number"
        value={amount}
        onChange={(e) => onAmountChange(e.target.value)} // Update the amount
        className="w-full px-4 py-2 border rounded-md"
        disabled={amountDisable} // Disable the input field for the converted amount
      />
      <select
        value={selectCurremcy} // Value for the selected currency
        onChange={(e) => onCurrencyChange(e.target.value)} // Update the currency when the user selects a new one
        className="w-full mt-2 px-4 py-2 border rounded-md"
      >
        {CurrencyOptions.map((currency) => (
          <option key={currency} value={currency}>
            {currency.toUpperCase()}
          </option>
        ))}
      </select>
    </div>
  );
};
  • Input Field: This lets the user type in the amount they want to convert. When the user types, the onAmountChange function is called, which updates the amount state in App.jsx.

  • Currency Dropdown: This lets the user select the currency (USD, INR, etc.) they are converting from or to. When the user selects a different currency, the onCurrencyChange function is called, which updates the from or to currency in App.jsx.

This component is reused for both the "From" and "To" currency sections. It displays the amount and allows users to select a currency.


5. The swap Function: Swapping Currencies

One of the key features of your app is the swap function, which lets the user switch the "From" and "To" currencies.

const swap = () => {
  setFrom(to); // Swap 'from' and 'to' currencies
  setTo(from);
  setConvertAmount(amount); // Set the converted amount to the original amount
  setAmount(convertAmount);  // Update the amount based on the converted value
};
  • When the user clicks the swap button, the from and to currencies are swapped.

  • It then updates the amount with the converted amount, so the user can see the new result in the swapped direction.

This is a simple, but useful feature to switch the direction of currency conversion without needing to re-enter the data.


6. The Conversion Logic

The most important part: calculating the converted amount. This happens when the user submits the form.

const convert = () => {
  setConvertAmount(amount * currencyInfo[to]); // Multiply the amount by the exchange rate for the selected 'to' currency
};
  • When the user submits the form by clicking the Convert button, the convert function is triggered.

  • How does the conversion happen? The app multiplies the entered amount by the conversion rate stored in currencyInfo[to] (where to is the selected currency).

    • For example, if the user enters 100 USD and selects INR as the target currency, it multiplies the amount (100) by the conversion rate from USD to INR (e.g., 83.0), and the converted amount will be 8300 INR.

This final result is stored in convertAmount and displayed on the UI.


7. The Final UI (Rendering Everything)

Lastly, after all the calculations and updates, the app renders the results.

return (
  <div className="w-full h-screen flex flex-wrap justify-center items-center bg-cover bg-no-repeat">
    <div className="w-full max-w-md mx-auto border border-gray-60 rounded-lg p-5 backdrop-blur-sm bg-white/30">
      <form onSubmit={(e) => { e.preventDefault(); convert(); }}>
        <div className="w-full mb-1">
          <InputBox
            label="From"
            amount={amount}
            CurrencyOptions={options}
            onCurrencyChange={(currency) => setFrom(currency)}
            onAmountChange={(amount) => setAmount(amount)}
            selectCurremcy={from}
          />
        </div>

        <button type="button" onClick={swap}>Swap</button>

        <div className="w-full mt-1 mb-4">
          <InputBox
            label="To"
            amount={convertAmount}
            CurrencyOptions={options}
            onCurrencyChange={(currency) => setTo(currency)}
            selectCurremcy={to}
            amountDisable={true}
          />
        </div>

        <button type="submit">Convert {from.toUpperCase()} to {to.toUpperCase()}</button>
      </form>
    </div>
  </div>
);
  • Form Submission: When the user clicks the Convert button, the convert() function is triggered, which calculates the converted amount and updates the UI.

  • Displaying Results: The converted amount is displayed in the "To" section, which is updated dynamically as the user makes changes.


Summary of the Data Flow

  1. User enters amount and selects currencies in the UI. This triggers state updates via React's useState.

  2. useCurrencyInfo fetches the latest conversion rates from the API.

  3. Conversion calculation happens based on the user's input and fetched conversion rates.

  4. Results are displayed back in the UI for the user to see.