DEV Community

Madhushan
Madhushan

Posted on

Auto-localize prices in React with react-currency-localizer-realtime

If you sell to international customers, showing prices in the visitor's local currency isn't a nice-to-have — it's a conversion-rate lever. But wiring it up usually turns into a small project: IP geolocation, exchange-rate fetching, caching, fallbacks, race conditions when the rate call is slower than render.

react-currency-localizer-realtime compresses all of that into a React hook and a component. Drop it in, pass a price, done.

Under the hood it uses real-time mid-market rates from the AllRatesToday API — 160+ currencies, updated every 60 seconds, sourced from Reuters/Refinitiv.

What you get

  • Real-time mid-market rates — no retail markup, no hidden spread
  • 🌍 Auto-detect the user's currency via IP geolocation (no API key needed for geolocation)
  • 💱 160+ currencies — major, minor, exotic, and precious metals
  • 🧠 Smart caching — 24h localStorage for geolocation, 1h memory cache for rates
  • 🔀 Three usage patterns — hook, component, or batch
  • 🎯 Manual override — skip geolocation with an explicit currency
  • 🔷 TypeScript-first — full type definitions
  • 📦 Zero runtime deps besides React itself
  • 🪶 ~4KB gzipped
  • 🛡️ Graceful fallbacks — shows the original price if anything fails

Install

npm install react-currency-localizer-realtime
Enter fullscreen mode Exit fullscreen mode

React 17+ is the only peer dependency.

Get a free API key at allratestoday.com/register.

1. The component — the simplest way

import { LocalizedPrice } from 'react-currency-localizer-realtime';

function ProductCard() {
  return (
    <div>
      <h3>Premium Plan</h3>
      <LocalizedPrice
        basePrice={99.99}
        baseCurrency="USD"
        apiKey="YOUR_API_KEY"
      />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

A visitor from Germany sees 92.34 €. A visitor from India sees ₹8,321. A visitor from the US just sees $99.99. No per-country routing, no SSR detection, no currency-switcher UI to build.

2. The hook — full control

Use useCurrencyConverter when you need loading/error states or custom formatting:

import { useCurrencyConverter } from 'react-currency-localizer-realtime';

function ProductPrice({ price }: { price: number }) {
  const { convertedPrice, localCurrency, isLoading, error } = useCurrencyConverter({
    basePrice: price,
    baseCurrency: 'USD',
    apiKey: 'YOUR_API_KEY',
  });

  if (isLoading) return <span>Loading price...</span>;
  if (error) return <span>${price}</span>; // graceful fallback

  return <span>{convertedPrice} {localCurrency}</span>;
}
Enter fullscreen mode Exit fullscreen mode

3. Manual override

Want to honor a user-picked currency? Pass it explicitly:

<LocalizedPrice
  basePrice={99.99}
  baseCurrency="USD"
  currency="JPY"           // override geolocation
  apiKey="YOUR_API_KEY"
/>
Enter fullscreen mode Exit fullscreen mode

Useful when you have a currency switcher in the header.

Why not just use Intl.NumberFormat?

Intl.NumberFormat handles formatting, not conversion. If you pass it 99.99 and tell it to format as JPY, it'll print ¥100 — wrong. You still need an actual exchange rate.

react-currency-localizer-realtime handles both: detect the currency, fetch the rate, apply it, format the output.

Performance notes

Two things usually hurt currency localizers on page load:

  1. Geolocation calls on every render. Fixed here with a 24h localStorage cache.
  2. Rate fetches on every price. Fixed here with a 1h in-memory cache shared across component instances.

Net effect: first visit triggers two network calls; every subsequent price on the page (and every return visit within 24h) is instant.

If a request fails, the component falls back to showing the original price rather than blanking — your customers never see a broken UI.

Real-world use case

This is the package I reach for whenever a WooCommerce/Shopify/custom storefront needs per-visitor pricing without forking the catalog by region. It's the missing middle between "one-currency site" and "separate regional installs."

Combine it with LocalizedPrice on product cards and a currency switcher in the header, and you've covered 95% of international-storefront UX in an afternoon.

Next steps

If you ship it on a live store, I'd love to see the before/after conversion numbers — drop them in the comments.

Top comments (0)