Back to Documentation
Build a Currency Converter App
Complete step-by-step tutorial to build a professional currency converter using React and the FXRateSync API
Beginner Friendly•30-45 minutes•React + TypeScript
What You'll Learn
- Setting up React with TypeScript
- Integrating FXRateSync API
- Real-time currency conversion
- Error handling best practices
- Professional UI with Tailwind CSS
- Production deployment ready
Prerequisites
- • Basic knowledge of React and TypeScript
- • Node.js 16+ installed on your machine
- • FXRateSync API key (free tier available)
- • Code editor (VS Code recommended)
Step 1: Project Setup
Let's start by creating a new React project with TypeScript and installing the necessary dependencies.
# Create a new React app with TypeScript npx create-react-app currency-converter --template typescript cd currency-converter # Install additional dependencies npm install axios tailwindcss npx tailwindcss init
Step 2: API Service Setup
Create a service to handle API calls to FXRateSync. This keeps your API logic organized and reusable.
// src/services/currencyService.ts
import axios from 'axios'
const API_BASE_URL = 'https://api.fxratesync.io/v1'
const API_KEY = process.env.REACT_APP_FX_API_KEY
export interface ConversionResult {
  from: string
  to: string
  amount: number
  converted_amount: number
  rate: number
  timestamp: string
}
export class CurrencyService {
  private static instance: CurrencyService
  
  static getInstance(): CurrencyService {
    if (!CurrencyService.instance) {
      CurrencyService.instance = new CurrencyService()
    }
    return CurrencyService.instance
  }
  async convertCurrency(
    from: string, 
    to: string, 
    amount: number
  ): Promise<ConversionResult> {
    try {
      const response = await axios.get(
        `${API_BASE_URL}/convert?from=${from}&to=${to}&amount=${amount}`,
        {
          headers: {
            'X-API-Key': API_KEY
          }
        }
      )
      return response.data
    } catch (error) {
      throw new Error('Failed to convert currency')
    }
  }
  async getSupportedCurrencies(): Promise<string[]> {
    // For this tutorial, we'll use a static list
    return ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY']
  }
}Step 3: Main Component
Now let's create the main currency converter component with a clean, professional interface.
// src/components/CurrencyConverter.tsx
import React, { useState, useEffect } from 'react'
import { CurrencyService, ConversionResult } from '../services/currencyService'
const CurrencyConverter: React.FC = () => {
  const [fromCurrency, setFromCurrency] = useState('USD')
  const [toCurrency, setToCurrency] = useState('EUR')
  const [amount, setAmount] = useState(100)
  const [result, setResult] = useState<ConversionResult | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [currencies, setCurrencies] = useState<string[]>([])
  const currencyService = CurrencyService.getInstance()
  useEffect(() => {
    loadCurrencies()
  }, [])
  const loadCurrencies = async () => {
    try {
      const supportedCurrencies = await currencyService.getSupportedCurrencies()
      setCurrencies(supportedCurrencies)
    } catch (err) {
      setError('Failed to load currencies')
    }
  }
  const handleConvert = async () => {
    if (amount <= 0) {
      setError('Amount must be greater than 0')
      return
    }
    setLoading(true)
    setError(null)
    try {
      const conversionResult = await currencyService.convertCurrency(
        fromCurrency,
        toCurrency,
        amount
      )
      setResult(conversionResult)
    } catch (err) {
      setError('Conversion failed. Please try again.')
    } finally {
      setLoading(false)
    }
  }
  const swapCurrencies = () => {
    setFromCurrency(toCurrency)
    setToCurrency(fromCurrency)
    setResult(null)
  }
  return (
    <div className="max-w-2xl mx-auto p-6 bg-background rounded-2xl shadow-xl">
      <h1 className="text-3xl font-bold text-center text-foreground mb-8">
        Currency Converter
      </h1>
      <div className="space-y-6">
        {/* Amount Input */}
        <div>
          <label className="block text-sm font-medium text-foreground mb-2">
            Amount
          </label>
          <input
            type="number"
            value={amount}
            onChange={(e) => setAmount(Number(e.target.value))}
            className="w-full px-4 py-3 border border-border rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
            placeholder="Enter amount"
          />
        </div>
        {/* Currency Selectors */}
        <div className="grid grid-cols-1 md:grid-cols-3 gap-4 items-end">
          <div>
            <label className="block text-sm font-medium text-foreground mb-2">
              From
            </label>
            <select
              value={fromCurrency}
              onChange={(e) => setFromCurrency(e.target.value)}
              className="w-full px-4 py-3 border border-border rounded-lg focus:ring-2 focus:ring-blue-500"
            >
              {currencies.map(currency => (
                <option key={currency} value={currency}>{currency}</option>
              ))}
            </select>
          </div>
          <div className="flex justify-center">
            <button
              onClick={swapCurrencies}
              className="px-4 py-2 text-primary hover:bg-primary/10 rounded-lg transition-colors"
            >
              ⇄ Swap
            </button>
          </div>
          <div>
            <label className="block text-sm font-medium text-foreground mb-2">
              To
            </label>
            <select
              value={toCurrency}
              onChange={(e) => setToCurrency(e.target.value)}
              className="w-full px-4 py-3 border border-border rounded-lg focus:ring-2 focus:ring-blue-500"
            >
              {currencies.map(currency => (
                <option key={currency} value={currency}>{currency}</option>
              ))}
            </select>
          </div>
        </div>
        {/* Convert Button */}
        <button
          onClick={handleConvert}
          disabled={loading}
          className="w-full bg-primary hover:bg-primary/90 disabled:opacity-50 text-background font-semibold py-3 px-6 rounded-lg transition-colors"
        >
          {loading ? 'Converting...' : 'Convert Currency'}
        </button>
        {/* Results */}
        {result && (
          <div className="bg-success/10 border border-success/30 rounded-lg p-6">
            <div className="text-center">
              <div className="text-3xl font-bold text-success-foreground mb-2">
                {result.converted_amount.toFixed(2)} {result.to}
              </div>
              <div className="text-sm text-success">
                {result.amount} {result.from} = {result.converted_amount.toFixed(2)} {result.to}
              </div>
              <div className="text-xs text-success mt-2">
                Rate: {result.rate.toFixed(4)} • {new Date(result.timestamp).toLocaleString()}
              </div>
            </div>
          </div>
        )}
        {/* Error Display */}
        {error && (
          <div className="bg-destructive/10 border border-destructive/30 rounded-lg p-4 text-destructive-foreground">
            {error}
          </div>
        )}
      </div>
    </div>
  )
}
export default CurrencyConverterStep 4: Environment Configuration
Create a `.env` file in your project root to store your API key securely.
# .env REACT_APP_FX_API_KEY=your_api_key_here
Security Note: Never commit your `.env` file to version control. Add it to your `.gitignore` file to keep your API key secure.
Step 5: Testing & Deployment
Test your application locally and prepare it for deployment.
# Test locally npm start # Build for production npm run build # Deploy to Netlify, Vercel, or your preferred hosting
Next Steps
Enhance Your App
- • Add historical rate charts
- • Implement rate alerts
- • Add favorite currency pairs
- • Include currency trend indicators
Ready to Deploy?
Get your free API key and start building amazing currency applications
Get Free API Key