Wie man Währungsbeträge in React Router v7 formatiert

Preise mit Währungssymbolen und Trennzeichen anzeigen

Problem

Die Anzeige von Preisen in Webanwendungen erfordert die Behandlung von zwei miteinander verbundenen Lokalisierungsaspekten: die verwendete Währung und die regionalen Konventionen für die Darstellung von Geldbeträgen. Ein Preis von 1200.50 US-Dollar erscheint für Benutzer in den Vereinigten Staaten als "$1,200.50", aber in Frankreich als "1 200,50 $US". Die Position des Währungssymbols, das Dezimaltrennzeichen, die Tausendergruppierung und die Abstände variieren je nach Gebietsschema. Wenn diese Konventionen nicht eingehalten werden, können Benutzer Beträge falsch interpretieren oder die Korrektheit des Preises anzweifeln, was das Vertrauen in die Anwendung untergräbt.

Die Herausforderung wird noch verstärkt, wenn eine Anwendung mehrere Regionen bedient oder Benutzern ermöglicht, Preise in verschiedenen Währungen anzuzeigen. Das Hardcoding von Formatierungsstrings oder die manuelle Platzierung von Symbolen erzeugt brüchigen Code, der bei Hinzufügen neuer Gebietsschemas oder Währungen nicht mehr funktioniert. Ohne einen systematischen Ansatz wird die Aufrechterhaltung konsistenter und korrekter Preisanzeigen in einer Anwendung fehleranfällig.

Lösung

Formatieren Sie Währungswerte unter Verwendung sowohl des Zielwährungscodes als auch des aktiven Gebietsschemas des Benutzers. Dieser Ansatz delegiert die komplexen Regeln der Währungsdarstellung an die Internationalisierungs-APIs des Browsers, die bereits die Formatierungskonventionen für Hunderte von Gebietsschema-Währungs-Kombinationen kodieren.

Indem ein numerischer Betrag, ein Währungscode und das aktuelle Gebietsschema an eine Formatierungsfunktion übergeben werden, wendet das System automatisch das korrekte Symbol, die Trennzeichen und das Layout an. Dies stellt sicher, dass Preise immer in einem für den Benutzer vertrauten Format erscheinen, unabhängig davon, welche Währung angezeigt wird oder in welcher Region sich der Benutzer befindet.

Schritte

1. Erstellen einer wiederverwendbaren Währungsformatierungskomponente

Erstellen Sie eine Komponente, die react-intl's FormattedNumber mit den Props style und currency verwendet, um Geldbeträge zu formatieren.

import { FormattedNumber } from "react-intl";

interface PriceProps {
  amount: number;
  currency: string;
}

export function Price({ amount, currency }: PriceProps) {
  return (
    <FormattedNumber value={amount} style="currency" currency={currency} />
  );
}

Die FormattedNumber-Komponente verwendet die formatNumber-API und akzeptiert Intl.NumberFormatOptions. Die Option style="currency" weist den Formatierer an, Währungssymbole einzubeziehen, und die Prop currency gibt an, welche Währung angezeigt werden soll.

2. Verwenden Sie die Price-Komponente in Route-Komponenten

Rendern Sie Preise in jeder React Router-Routenkomponente, indem Sie den numerischen Wert und den Währungscode übergeben.

import { Price } from "~/components/Price";

export default function ProductPage() {
  const product = {
    name: "Wireless Headphones",
    price: 129.99,
    currency: "USD",
  };

  return (
    <div>
      <h1>{product.name}</h1>
      <p>
        <Price amount={product.price} currency={product.currency} />
      </p>
    </div>
  );
}

Die Price-Komponente formatiert den Betrag automatisch entsprechend der in IntlProvider konfigurierten Locale. Für eine US-Locale wird "$129.99" gerendert; für eine deutsche Locale mit derselben USD-Währung wird "129,99 $" gerendert.

3. Formatieren Sie Währungen bei Bedarf imperativ

Für Szenarien, in denen Sie direkt auf den formatierten String zugreifen müssen, verwenden Sie den useIntl-Hook, um auf die formatNumber-Methode zuzugreifen.

import { useIntl } from "react-intl";

export default function CheckoutSummary() {
  const intl = useIntl();
  const subtotal = 89.99;
  const tax = 7.2;
  const total = subtotal + tax;

  const formattedTotal = intl.formatNumber(total, {
    style: "currency",
    currency: "EUR",
  });

  return (
    <div>
      <h2>Order Summary</h2>
      <dl>
        <dt>Subtotal</dt>
        <dd>
          {intl.formatNumber(subtotal, {
            style: "currency",
            currency: "EUR",
          })}
        </dd>
        <dt>Tax</dt>
        <dd>
          {intl.formatNumber(tax, {
            style: "currency",
            currency: "EUR",
          })}
        </dd>
        <dt>Total</dt>
        <dd aria-label={`Total: ${formattedTotal}`}>
          <strong>{formattedTotal}</strong>
        </dd>
      </dl>
    </div>
  );
}

Die formatNumber-Methode akzeptiert einen Wert und ein Options-Objekt mit FormatNumberOptions. Dies ist nützlich, wenn Sie den formatierten String für Attribute, Logging oder nicht-JSX-Kontexte benötigen.

4. Steuern Sie die Dezimalpräzision für Ganzzahl-Währungen

Einige Währungen verwenden keine Nachkommastellen. Passen Sie die Anzahl der Dezimalstellen an die Währungskonventionen an.

import { FormattedNumber } from "react-intl";

interface PriceProps {
  amount: number;
  currency: string;
}

export function Price({ amount, currency }: PriceProps) {
  const isWholeNumberCurrency = currency === "JPY" || currency === "KRW";

  return (
    <FormattedNumber
      value={amount}
      style="currency"
      currency={currency}
      minimumFractionDigits={isWholeNumberCurrency ? 0 : 2}
      maximumFractionDigits={isWholeNumberCurrency ? 0 : 2}
    />
  );
}

Der japanische Yen verwendet keine Untereinheit, daher werden Beträge ohne Dezimalstellen angezeigt. Die Optionen minimumFractionDigits und maximumFractionDigits überschreiben bei Bedarf das standardmäßige Dezimalverhalten.