React hooks and components for the UniRate currency-exchange API.
useExchangeRate(from, to)— single rateuseRates(from)— full rate table for a baseuseConvert(from, to, amount)— converted amountuseCurrencies()— list of supported codes (~600)useHistoricalRate(date, from, to)— historical rate (Pro)<Currency amount from to />— drop-in€92.50JSX<Rate from to />— drop-in1.0823JSX<UniRateProvider>— one client for the whole tree- Zero runtime deps. Native
fetch. AbortController cleanup on unmount.
npm install @unirate/react
# or
pnpm add @unirate/react
# or
yarn add @unirate/reactPeer dep: react ^18 || ^19. Requires Node 18.17+ for build/server use.
import { UniRateProvider, useExchangeRate, Currency } from "@unirate/react";
function App() {
return (
<UniRateProvider apiKey={process.env.NEXT_PUBLIC_UNIRATE_API_KEY!}>
<Cart />
</UniRateProvider>
);
}
function Cart() {
const { data: rate, isLoading } = useExchangeRate("USD", "EUR");
if (isLoading) return <p>Loading…</p>;
return (
<p>
1 USD = {rate} EUR. Your total:{" "}
<Currency amount={42.99} from="USD" to="EUR" />
</p>
);
}Get a free API key at unirateapi.com — the free tier covers latest rates and conversions for ~600 currencies including crypto. Historical rates, time-series, and commodity feeds require Pro.
Every hook returns the same shape:
interface QueryState<T> {
data: T | undefined;
error: Error | undefined;
isLoading: boolean; // true on the very first fetch only
isFetching: boolean; // true on every refetch including the first
refetch: () => void; // re-run the request manually
}Every hook also accepts an options object:
{
client?: UniRateClient; // override the provider's client
enabled?: boolean; // skip the fetch until true (default true)
}const { data, error, isLoading } = useExchangeRate("USD", "EUR");
// data: 0.92Returns the full rate table for a base.
const { data } = useRates("USD");
// data: { EUR: 0.92, GBP: 0.80, JPY: 154.21, ... }const { data } = useConvert("USD", "EUR", 100);
// data: 92.50const { data: codes } = useCurrencies();
// data: ["USD", "EUR", "GBP", "JPY", "BTC", ...]Pro endpoint. Returns
ProRequiredErroron the free tier.
const { data } = useHistoricalRate("2025-01-01", "USD", "EUR");
// data: 0.851Renders one converted, locale-formatted amount.
<Currency amount={1234.56} from="USD" to="EUR" />
// → "€1,141.97"
<Currency amount={100} to="EUR" loading="Converting…" />
// from defaults to "USD"; renders "Converting…" until the rate arrives
<Currency
amount={100}
from="USD"
to="EUR"
fallback={(err) => <span title={err.message}>n/a</span>}
/>On error with no fallback prop, <Currency> falls back to the unconverted amount in the source currency so layouts don't collapse.
Renders a bare exchange-rate number.
<Rate from="EUR" to="USD" /> // → "1.0823"
<Rate from="EUR" to="USD" decimals={2} /> // → "1.08"Putting an API key directly in client-side React means the key ships to every visitor's browser. For production deployments you have two options:
-
Proxy through your backend. Point
baseUrlat your own endpoint and have that endpoint hold the realUNIRATE_API_KEY:<UniRateProvider apiKey="placeholder" baseUrl="/api/unirate" />
The placeholder still passes the client's "apiKey is required" check; your server inspects requests and inserts the real key before forwarding to
api.unirateapi.com. -
Free-tier-only public key. Free-tier UniRate keys are rate-limited per key; if a leaked key only unlocks endpoints you don't mind being shared, shipping it client-side is acceptable.
Server-only React (RSC, Remix loaders, server actions): you can use the raw UniRateClient directly without the provider, since there's no client component involved.
import { UniRateClient } from "@unirate/react/client";
// in a server action / loader:
const client = new UniRateClient({ apiKey: process.env.UNIRATE_API_KEY! });
const rate = await client.getRate("USD", "EUR");The same error classes the hooks expose are also exported for instanceof checks:
AuthenticationError— 401, bad / missing keyRateLimitError— 429InvalidCurrencyError— 404, unknown currency codeInvalidRequestError— 400, bad paramsProRequiredError— 403, endpoint requires a Pro subscriptionUniRateError— base class for any other failure
const { error } = useExchangeRate("USD", "XYZ");
if (error instanceof InvalidCurrencyError) {
return <p>Unsupported currency.</p>;
}UniRate ships official client libraries and framework integrations across the ecosystem. The repos below are all maintained under the UniRate-API org.
- Languages: Python · Node.js / TypeScript · Go · Rust · Java · Ruby · PHP · .NET · Swift
- Web frameworks: Django / Wagtail · FastAPI · Flask · React · tRPC
- Static-site generators: Astro · Eleventy · Hugo
- Data / orchestration: Airflow · dbt · LangChain
- Workflow / no-code: n8n · Google Sheets · MCP server
- Editors / tools: VS Code · Obsidian
- Specialty bridges: NodaMoney (.NET)
Get a free API key at unirateapi.com.
MIT © UniRate API