Comment Créer un Convertisseur de Devises avec React et une API de Taux de Change en Temps Réel
Créer un convertisseur de devises avec React est un excellent projet pour les développeurs qui souhaitent pratiquer l'intégration d'API, les hooks React et la gestion d'état dans des applications réelles. Dans ce tutoriel étape par étape, vous allez construire un convertisseur de devises entièrement fonctionnel qui récupère des taux de change en temps réel depuis une API, prend en charge plus de 170 devises et gère les erreurs avec élégance — le tout en utilisant des patterns React modernes.
Si vous débutez et souhaitez comprendre le fonctionnement des taux de change, consultez notre explication sur les taux de change avant de commencer.
Ce Que Vous Allez Créer
À la fin de ce tutoriel, vous aurez un convertisseur de devises React qui :
- Récupère les taux de change en temps réel depuis l'API Finexly
- Prend en charge plus de 170 devises via un menu déroulant
- Convertit les montants en temps réel à mesure que l'utilisateur tape (avec debouncing)
- Gère les états de chargement et les erreurs API élégamment
- Affiche le taux et l'horodatage de la dernière mise à jour
Structure du projet :
currency-converter/
├── src/
│ ├── components/
│ │ └── CurrencyConverter.tsx
│ ├── hooks/
│ │ └── useExchangeRate.ts
│ ├── App.tsx
│ └── main.tsx
├── package.json
└── vite.config.tsPrérequis
Avant de commencer, assurez-vous d'avoir :
- Node.js 18+ installé
- Une connaissance de base des hooks React (
useState,useEffect) - Une clé API Finexly gratuite (environ 30 secondes pour l'obtenir)
Étape 1 : Configurer Votre Projet React
Nous utiliserons Vite comme outil de build :
npm create vite@latest currency-converter -- --template react-ts
cd currency-converter
npm install
npm run devVotre serveur de développement démarrera sur http://localhost:5173.
Étape 2 : Comprendre l'API Finexly
L'API Finexly fournit des taux de change en temps réel et historiques pour plus de 170 devises via une interface REST simple :
GET https://finexly.com/api/v1/latest?base=USDUne réponse typique ressemble à :
{
"base": "USD",
"date": "2026-04-07",
"rates": {
"EUR": 0.9182,
"GBP": 0.7871,
"JPY": 151.42
},
"timestamp": 1744012800
}Incluez votre clé dans l'en-tête de la requête :
Authorization: Bearer VOTRE_CLE_APIVous pouvez vous inscrire pour un plan gratuit incluant 1 000 requêtes par mois.
Étape 3 : Créer le Hook Personnalisé
Créez le fichier src/hooks/useExchangeRate.ts :
import { useState, useEffect, useCallback } from "react";
interface ExchangeRateResult {
rates: Record<string, number> | null;
loading: boolean;
error: string | null;
lastUpdated: Date | null;
}
const API_KEY = import.meta.env.VITE_FINEXLY_API_KEY;
const BASE_URL = "https://finexly.com/api/v1";
const rateCache: Record<string, { rates: Record<string, number>; timestamp: number }> = {};
const CACHE_TTL_MS = 5 * 60 * 1000;
export function useExchangeRate(baseCurrency: string): ExchangeRateResult {
const [rates, setRates] = useState<Record<string, number> | null>(null);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const [lastUpdated, setLastUpdated] = useState<Date | null>(null);
const fetchRates = useCallback(async (base: string) => {
const cached = rateCache[base];
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) {
setRates(cached.rates);
setLastUpdated(new Date(cached.timestamp));
return;
}
setLoading(true);
setError(null);
try {
const res = await fetch(`${BASE_URL}/latest?base=${base}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
if (!res.ok) throw new Error(`Erreur API : ${res.status} ${res.statusText}`);
const data = await res.json();
rateCache[base] = { rates: data.rates, timestamp: Date.now() };
setRates(data.rates);
setLastUpdated(new Date());
} catch (err) {
setError(err instanceof Error ? err.message : "Échec de la récupération des taux de change");
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
if (baseCurrency) fetchRates(baseCurrency);
}, [baseCurrency, fetchRates]);
return { rates, loading, error, lastUpdated };
}Étape 4 : Créer le Composant CurrencyConverter
Créez src/components/CurrencyConverter.tsx :
import { useState, useMemo } from "react";
import { useExchangeRate } from "../hooks/useExchangeRate";
const CURRENCIES = [
"USD", "EUR", "GBP", "JPY", "CAD", "AUD", "CHF", "CNY",
"INR", "MXN", "BRL", "KRW", "SGD", "HKD", "NOK", "SEK",
];
export default function CurrencyConverter() {
const [amount, setAmount] = useState<string>("100");
const [baseCurrency, setBaseCurrency] = useState<string>("USD");
const [targetCurrency, setTargetCurrency] = useState<string>("EUR");
const { rates, loading, error, lastUpdated } = useExchangeRate(baseCurrency);
const convertedAmount = useMemo(() => {
if (!rates || !amount) return null;
const numAmount = parseFloat(amount);
if (isNaN(numAmount) || numAmount < 0) return null;
const rate = rates[targetCurrency];
return rate ? (numAmount * rate).toFixed(2) : null;
}, [rates, amount, targetCurrency]);
const handleSwap = () => {
setBaseCurrency(targetCurrency);
setTargetCurrency(baseCurrency);
};
return (
<div className="converter-card">
<h2>Convertisseur de Devises en Temps Réel</h2>
<div className="input-row">
<label htmlFor="amount">Montant</label>
<input
id="amount"
type="number"
min="0"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Entrez le montant"
/>
</div>
<div className="currency-row">
<div className="select-group">
<label htmlFor="base">De</label>
<select id="base" value={baseCurrency} onChange={(e) => setBaseCurrency(e.target.value)}>
{CURRENCIES.map((c) => <option key={c} value={c}>{c}</option>)}
</select>
</div>
<button className="swap-btn" onClick={handleSwap} aria-label="Inverser les devises">⇄</button>
<div className="select-group">
<label htmlFor="target">Vers</label>
<select id="target" value={targetCurrency} onChange={(e) => setTargetCurrency(e.target.value)}>
{CURRENCIES.map((c) => <option key={c} value={c}>{c}</option>)}
</select>
</div>
</div>
<div className="result-area">
{loading && <p>Récupération des derniers taux...</p>}
{error && <p className="error-text">⚠ {error}</p>}
{!loading && !error && convertedAmount !== null && (
<>
<p className="converted-value">
{parseFloat(amount).toLocaleString()} {baseCurrency} =
<strong>{parseFloat(convertedAmount).toLocaleString()} {targetCurrency}</strong>
</p>
{lastUpdated && <p>Taux mis à jour : {lastUpdated.toLocaleTimeString()}</p>}
</>
)}
</div>
</div>
);
}Étape 5 : Variables d'Environnement
Créez un fichier .env à la racine du projet :
VITE_FINEXLY_API_KEY=votre_cle_api_iciAjoutez .env à votre .gitignore pour protéger votre clé.
Étape 6 : Connecter l'Application
Mettez à jour src/App.tsx :
import CurrencyConverter from "./components/CurrencyConverter";
function App() {
return (
<main>
<CurrencyConverter />
<footer>
<p>Taux de change fournis par <a href="https://finexly.com">Finexly</a></p>
</footer>
</main>
);
}
export default App;Gestion des Cas Limites
Un convertisseur prêt pour la production doit gérer les entrées invalides, avertir lorsque la même devise est sélectionnée pour la source et la cible, et traiter les pannes réseau via l'état d'erreur dans le hook.
Optimisation des Performances avec le Debouncing
// src/hooks/useDebounce.ts
import { useState, useEffect } from "react";
export function useDebounce<T>(value: T, delayMs: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delayMs);
return () => clearTimeout(timer);
}, [value, delayMs]);
return debouncedValue;
}Pour Aller Plus Loin
Des améliorations de haute valeur incluent : un graphique de taux historiques via l'API historique de Finexly, une conversion multi-devises simultanée, des devises favorites persistées dans localStorage, et le rendu côté serveur avec Next.js.
Questions Fréquentes
Quelle est la meilleure API de taux de change pour React ? Pour les applications React, vous avez besoin d'une API REST qui prend en charge CORS. L'API Finexly prend en charge CORS sur tous les plans et couvre plus de 170 devises avec un niveau gratuit.
À quelle fréquence les taux de change sont-ils mis à jour ? L'API Finexly met à jour les taux toutes les 60 secondes pour les plans en temps réel et une fois par jour pour les plans standard.
Puis-je utiliser une API de change dans une application React côté client ? Oui, si l'API prend en charge CORS. Pour les applications en production, il est recommandé de router les requêtes via votre propre backend.
Comment éviter d'exposer ma clé API dans React ?
Pour le développement, utilisez le fichier .env de Vite avec le préfixe VITE_. Pour la production, routez les requêtes via un Route Handler Next.js ou une fonction serverless.
Comment convertir entre deux devises qui ne sont pas USD ? L'API Finexly prend en charge n'importe quelle devise de base sur tous les plans, ce qui simplifie grandement cette opération.
Prêt à ajouter des taux de change en temps réel à votre application React ? Obtenez votre clé API Finexly gratuite — sans carte bancaire requise. Commencez avec 1 000 requêtes gratuites par mois et évoluez à mesure que vous grandissez.
Explore More
Vlado Grigirov
Senior Currency Markets Analyst & Financial Strategist
Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...
View full profile →