# React Currency Input: Intl-Formatierung ohne Cursor-Sprünge

> So baust du einen React Currency Input, der beim Tippen mit Intl formatiert, den Cursor stehen lässt, das Symbol nach Locale setzt und eine reine Zahl sendet.

- Autor: [Serban Rusu](https://wingo-ui.com/blog/authors/serban), Founder of Wingo UI
- Veröffentlicht: 16. Okt. 2026
- Kategorie: [Komponenten-Guides](https://wingo-ui.com/de/blog/category/components)
- Lesezeit: 10 Min.
- Kanonische URL: https://wingo-ui.com/de/blog/react-currency-input
- Englische Fassung: https://wingo-ui.com/blog/react-currency-input

## Kurz gesagt

Ein guter React Currency Input gruppiert die Ziffern beim Tippen mit Intl.NumberFormat, setzt den Cursor über die Zahl der Ziffern statt der Zeichen zurück, zeigt das Symbol dort, wo die Locale es hinsetzt ($1,234.56, 1.234,56 €), und gibt deinem Code eine reine Zahl wie 1234.56. Das Auffüllen auf die Nachkommastellen der Währung und das Begrenzen auf min und max passieren beim Blur, nie bei jedem Tastendruck. Der Currency Input von Wingo UI (Pro) macht das mit Währungsauswahl und Schnellbeträgen, und die kostenlosen number-format-Helfer geben dir dasselbe Parsing und dieselbe Cursor-Logik für dein eigenes Feld.

Ein React Currency Input wirkt einfach, bis echte Menschen etwas eintippen. Jemand in Berlin tippt `1234,5` und erwartet `1.234,5`, jemand in Chicago tippt `1234.5` und erwartet `1,234.5`, und beide erwarten, dass der Cursor direkt hinter der Ziffer bleibt, die sie gerade getippt haben. Deine API will `1234.5` als Zahl und daneben einen Währungscode. Dieser Guide zeigt, was ein gutes Geldfeld können muss, warum der Cursor in selbst gebauten Versionen springt und wie du das mit Intl behebst, und wie du den [Currency Input](https://wingo-ui.com/components/currency-input) von Wingo UI in einem Formular einsetzt.

## Was muss ein React Currency Input können?

Ein guter React Currency Input formatiert schon beim Tippen in der Locale des Nutzers, lässt den Cursor, wo er war, und gibt deinem Code eine reine Zahl. Im Detail sind es sieben Verhaltensweisen:

1. **Beim Tippen formatieren, in der Locale des Nutzers.** Tausendertrennzeichen erscheinen, sobald Ziffern dazukommen (`1,234` in en-US, `1.234` in de-DE), mit den Trennzeichen, die `Intl.NumberFormat` für diese Locale meldet.
2. **Den Cursor stehen lassen.** Ein eingefügtes Trennzeichen darf den Cursor nicht ans Ende des Felds werfen.
3. **Beide Dezimaltasten annehmen.** Die Ziffernblöcke auf dem Smartphone zeigen je nach Systemsprache einen Punkt oder ein Komma. Beide sollten also zum Dezimaltrennzeichen der Locale werden, wenn sie am Ende getippt werden.
4. **Das Symbol dort hinsetzen, wo die Locale es hinsetzt.** `$1,234.56` in en-US, `1.234,56 €` in de-DE, `1.234,56 lei` in ro-RO. Das Symbol steht neben dem Text und ist nie Teil des bearbeitbaren Werts.
5. **Die Nachkommastellen der Währung respektieren.** USD hat 2, JPY hat 0, BHD hat 3. Ein Yen-Feld ignoriert die Dezimaltaste.
6. **Beim Blur festschreiben.** `1,234.5` wird zu `1,234.50` aufgefüllt und auf min und max begrenzt, wenn das Feld den Fokus verliert, nicht während jemand noch mitten in der Zahl steckt.
7. **Ein sauberer Wert nach außen.** Dein State und dein Formular bekommen `1234.5`, nie `"$1,234.50"`.

## Warum springt der Cursor in einem formatierten Geldfeld?

Der Cursor springt, weil sich die Länge des Strings unter ihm ändert. Du tippst `5` hinter `1,234`, und dein `onChange` schreibt `12,345`. React setzt den Wert des Felds auf einen neuen String, der Browser kann nicht wissen, wohin deine alte Cursorposition darin gehört, und der Cursor landet am Ende. Hast du mitten in der Zahl getippt, geht der nächste Tastendruck an die falsche Stelle.

Die Lösung: Zähl Ziffern, nicht Zeichenpositionen. Vor dem Formatieren zählst du die Ziffern links vom Cursor. Nach dem Formatieren gehst du den neuen String durch und setzt den Cursor hinter dieselbe Anzahl Ziffern. Trennzeichen, die der Formatter hinzufügt oder entfernt, zählen nie mit, also verschieben sie ihn auch nie. Die kostenlosen [number-format-Helfer](https://wingo-ui.com/components/number-format) liefern genau diesen Ansatz als `digitsBeforeCaret` und `caretAfterDigits`, dazu `formatEditable` (formatiert Text beim Tippen neu, ohne einen `.` oder Nullen am Ende zu verlieren), `parseNumber` (Parsing nach Locale) und `getCurrencyParts` (wohin das Symbol gehört).

Hier ein minimales Geldfeld, das nur auf diesen Helfern aufbaut:

```tsx
"use client";

import { useLayoutEffect, useRef, useState, type ChangeEvent } from "react";
import {
  caretAfterDigits,
  digitsBeforeCaret,
  formatEditable,
  getCurrencyParts,
  parseNumber,
} from "@/lib/number-format";

type MoneyFieldProps = {
  locale?: string;
  currency?: string;
  onValueChange?: (value: number | null) => void;
};

export function MoneyField({ locale = "en-US", currency = "USD", onValueChange }: MoneyFieldProps) {
  const parts = getCurrencyParts(currency, locale);
  const [text, setText] = useState("");
  const inputRef = useRef<HTMLInputElement>(null);
  const caretRef = useRef<number | null>(null);

  // cursor zurücksetzen, sobald react den neuen text geschrieben hat
  useLayoutEffect(() => {
    if (caretRef.current == null || !inputRef.current) return;
    inputRef.current.setSelectionRange(caretRef.current, caretRef.current);
    caretRef.current = null;
  });

  function handleChange(event: ChangeEvent<HTMLInputElement>) {
    const raw = event.target.value;
    const digits = digitsBeforeCaret(raw, event.target.selectionStart ?? raw.length, locale);
    const next = formatEditable(raw, locale, { maxDecimals: parts.fractionDigits, allowNegative: false });
    caretRef.current = caretAfterDigits(next, digits, locale);
    setText(next);
    onValueChange?.(parseNumber(next, locale));
  }

  return (
    <div className="flex h-10 items-center gap-1 rounded-[10px] bg-foreground/5 px-3 text-sm">
      {parts.position === "prefix" && <span aria-hidden className="text-muted-foreground">{parts.symbol}</span>}
      <input
        ref={inputRef}
        value={text}
        onChange={handleChange}
        inputMode="decimal"
        autoComplete="transaction-amount"
        aria-label={`Betrag in ${currency}`}
        className="min-w-0 flex-1 bg-transparent tabular-nums outline-none"
      />
      {parts.position === "suffix" && <span aria-hidden className="text-muted-foreground">{parts.symbol}</span>}
    </div>
  );
}
```

`getCurrencyParts("USD", "en-US")` gibt `{ symbol: "$", position: "prefix", spaced: false, fractionDigits: 2 }` zurück und `getCurrencyParts("EUR", "de-DE")` das Euro-Zeichen als Suffix mit Leerzeichen. Dieselbe Komponente ordnet sich also je nach Locale selbst an. Weil Trennzeichen und Symbolposition aus Intl kommen statt aus fest eingetragenen `,` und `.`, funktioniert ein Intl.NumberFormat Currency Input in Berlin und Chicago gleichermaßen. `getCurrencyParts` nimmt standardmäßig `narrowSymbol`, das Symbol, das Menschen tatsächlich schreiben: In ro-RO liefert die Standardanzeige `symbol` von Intl `1.234,56 RON`, mit narrowSymbol steht dort `1.234,56 lei`.

Probier die Helfer unten einzeln aus. Die Demo steht auf de-DE, also gruppiert der Punkt die Tausender und das Komma trennt die Dezimalstellen. Tipp mitten in der Zahl: Die Gruppierung ändert sich, der Cursor bleibt stehen, und die Zeilen zeigen die geparste Zahl.

> Live-Demo (Number format): Klick zwischen zwei Ziffern und tipp eine weitere: Die Punkte wandern, und der Cursor bleibt hinter der getippten Ziffer. Die Zeile parseNumber zeigt die reine Zahl. Probier sie unter [Number format](https://wingo-ui.com/components/number-format) aus und installier sie mit `npx wingo-ui@latest add number-format`.

Diese Skizze deckt den Normalfall ab. Sie füllt beim Blur nicht auf, begrenzt nicht, ändert den Wert nicht per Pfeiltaste und liest kein eingefügtes `$1,234.56`. In de-DE wird ein Punkt, der hinter `1.234` getippt wird, als weiteres Tausendertrennzeichen verworfen, statt zum Dezimalkomma zu werden. Backspace auf einem Trennzeichen fängt sie auch nicht ab: Der Formatter setzt das Trennzeichen sofort wieder ein, und die Taste wirkt tot. Dazu kommt ein leiserer Bug: Tippst du einen Buchstaben, gibt `formatEditable` denselben Text zurück, `setText` verwirft das Update, React schreibt den alten Wert zurück ins DOM, und der Cursor springt trotzdem ans Ende. Die vollständige Komponente behandelt all das. Den letzten Fall löst sie, indem sie den Cursor selbst zurücksetzt, wenn ein Tastendruck nichts ändert.

## Wie nutzt du den Currency Input von Wingo UI?

Installier ihn mit `npx wingo-ui@latest add currency-input` und render ihn dann mit einer Locale, einem Wert und einem `name` für Formulare:

```tsx
"use client";

import { useState } from "react";
import { CurrencyInput } from "@/components/ui/currency-input";

export function ListingPrice() {
  const [price, setPrice] = useState<number | null>(1250);
  const [currency, setCurrency] = useState("USD");

  return (
    <CurrencyInput
      name="price"
      currencyName="currency"
      label="Preis"
      description="Der Preis enthält Steuern"
      locale="en-US"
      currencies={["USD", "EUR", "GBP"]}
      currency={currency}
      onCurrencyChange={setCurrency}
      value={price}
      onValueChange={setPrice}
      min={1}
      error={price !== null && price < 1 ? "Der Mindestpreis beträgt $1" : undefined}
      required
    />
  );
}
```

Tipp unten einen Betrag ein, klick dann auf den Währungs-Button und wähl einen anderen Code: Das Symbol ändert sich, der Betrag bleibt gleich.

> Live-Demo (Currency Input): Klick auf den Preis, tipp 1234.5 und drück Tab: Er wird zu 1,234.50 aufgefüllt. Klick noch einmal hinein, drück ArrowUp für plus 1, klick dann auf den Button USD und wähl EUR: Das Symbol ändert sich, der Betrag wird nicht umgerechnet. Probier sie unter [Currency Input](https://wingo-ui.com/components/currency-input) aus und installier sie mit `npx wingo-ui@latest add currency-input`.

Die wichtigsten Props:

- **`value` und `onValueChange`** tragen den Betrag in der Haupteinheit (`1234.56`), mit `null` für ein leeres Feld. `onValueChange` wird live beim Tippen ausgelöst und ist bis zum Blur nicht begrenzt. Berücksichtige das bei der Validierung.
- **`locale`** legt die Trennzeichen und die Seite des Symbols fest. Lässt du sie leer, liest das Feld die Locale aus `UIProvider` oder `LocaleProvider`. Fehlen beide, rendert der Server `en-US`, und der Browser wechselt nach der Hydration zur Sprache der Seite. Setz also eine Locale, wenn schon der erste Paint stimmen muss.
- **`defaultCurrency` / `currency`** nehmen einen ISO-4217-Code. Die Nachkommastellen folgen ihm (`decimals={-1}`, der Standard, bedeutet „die der Währung“), also tippt man bei USD zwei Nachkommastellen und bei JPY keine.
- **`currencies`** mit zwei oder mehr Codes zeigt am Ende des Felds einen kompakten Button mit dem Code. Ein Währungswechsel rechnet den Betrag nie um; hat die neue Währung weniger Nachkommastellen, wird der Betrag darauf gerundet.
- **`min`, `max` und `step`** begrenzen beim Blur oder bei Enter, markieren das Feld als ungültig, solange der Wert außerhalb liegt, und legen fest, was ArrowUp und ArrowDown addieren (mit Shift zehn Schritte).
- **`presets`** rendert Schnellbeträge als Chips unter dem Feld, das Muster aus Spenden- und Trinkgeldformularen.
- **`allowNegative`** lässt ein Minus zu, für Erstattungen oder Saldokorrekturen.

## Welchen Wert sendet der Currency Input ab?

Mit `name` rendert der Currency Input ein verstecktes Feld, dessen Wert der Betrag als `"1234.56"` mit Dezimalpunkt ist, oder leer, wenn das Feld leer ist. Das sichtbare Feld hat kein `name`-Attribut. `currencyName` ergänzt ein zweites verstecktes Feld mit dem gewählten Code. Ein einfaches Formular oder eine Server Action liest also Zahlen statt formatiertem Text:

```tsx
import { CurrencyInput } from "@/components/ui/currency-input";
import { Button } from "@/components/ui/button";

async function savePrice(formData: FormData) {
  "use server";
  const amount = Number(formData.get("price"));
  const currency = String(formData.get("currency") ?? "USD");
  if (!Number.isFinite(amount) || amount < 1) return;
  // untereinheiten speichern, damit keine gleitkommarechnung in der datenbank landet
  const cents = Math.round(amount * 100);
  console.log("speichern", cents, currency);
}

export function PriceForm() {
  return (
    <form action={savePrice} className="flex flex-col gap-4">
      <CurrencyInput name="price" currencyName="currency" currencies={["USD", "EUR"]} label="Preis" locale="en-US" min={1} required />
      <Button type="submit">Preis speichern</Button>
    </form>
  );
}
```

Das versteckte Feld aktualisiert sich im selben Event wie der Tastendruck. Drückst du im Feld Enter, wird der Betrag aufgefüllt und der neue Wert in einem Zug abgeschickt. Runde, schneide nie ab: `1.15 * 100` ergibt in JavaScript `114.99999999999999`, also liefert `Math.trunc` 114, wo `Math.round` 115 liefert. Das `* 100` setzt eine Währung mit zwei Nachkommastellen voraus; für JPY oder BHD multiplizierst du stattdessen mit `10 ** decimals`.

## Wie schlägt sich der Currency Input gegen react-currency-input-field und einen shadcn Currency Input?

react-currency-input-field ist das kostenlose, spezialisierte Paket, react-number-format der Allzweck-Formatter, shadcn/ui hat kein Geldfeld, und die Komponente von Wingo UI ist eine Pro-Quelldatei mit eingebauter Währungsauswahl und eingebautem Smartphone-Verhalten. Stand Oktober 2026, laut npm und der Doku der jeweiligen Projekte:

| Option | Version | Lizenz | Ausgabewert | Hinweise |
|---|---|---|---|---|
| [react-currency-input-field](https://github.com/cchanxzy/react-currency-input-field) | 4.0.14 | MIT | String, dazu `values.float` | `intlConfig` für Locale und Währung, Abkürzungen k / m / b standardmäßig an |
| [react-number-format](https://www.npmjs.com/package/react-number-format) | 5.4.5 | MIT | `floatValue` in `onValueChange` | allgemeine Zahlenformatierung und Masken, Styling machst du selbst |
| [shadcn/ui](https://ui.shadcn.com/docs/components) | n/a | MIT | n/a | kein Währungs- oder Zahlen-Input in der offiziellen Liste; Input und Input Group gibt es |
| Wingo UI Currency Input | kopierter Quellcode | Pro | Zahl im State, `"1234.56"` im Formular | Währungsauswahl, Presets, Liste als Bottom Sheet auf Smartphones |

Suchst du ein kostenloses npm-Paket für ein React Currency Input Field und stylst es gern selbst, ist react-currency-input-field die spezialisierte Wahl: Lies für die Zahl `values.float` aus seinem `onValueChange`, denn das erste Argument ist ein String, und setz `disableAbbreviations`, wenn ein getipptes `k` nicht Tausend bedeuten soll. Suchst du nach einem shadcn Currency Input oder einem Beispiel für einen React Money Input, ist die übliche Abkürzung ein Input mit `type="number"` und einem Dollar-Icon in einer Input Group. Das bringt dir weder Gruppierung noch Locale. Die Komponente von Wingo UI passt, wenn du das Feld, den fertigen Aufbau mit Label und Fehlermeldung und das Smartphone-Verhalten in einer Datei willst, die dir gehört.

## Wie funktioniert der Currency Input auf dem Smartphone und mit der Tastatur?

Auf Smartphones nutzt der Currency Input `inputMode="decimal"` für den Dezimal-Ziffernblock und `enterKeyHint="done"`, und es nimmt beide Trenntasten an, weil der Ziffernblock das Zeichen der Systemsprache zeigt. Der Text ist 16px groß, damit iOS Safari nie hineinzoomt, das Feld in Größe md wächst auf Touchscreens auf 44px, und der Währungs-Button und die Preset-Chips haben Tippflächen von 44px. Unter 768px öffnet sich die Währungsliste als Bottom Sheet statt als Popover (`responsive={false}` behält das Popover). Die Dezimal-Ziffernblöcke von iOS haben keine Minustaste. Mit `allowNegative` entsteht ein negativer Betrag also über ArrowDown oder eine Hardware-Tastatur.

Bei Tastaturbedienung markiert das Feld beim Fokus den ganzen Betrag, sodass Tippen ihn ersetzt (`selectOnFocus`, standardmäßig an). ArrowUp und ArrowDown ändern den Wert um einen Schritt, Enter übernimmt den Wert und sendet das Formular trotzdem ab, und mit `clearable` leert Escape das Feld. Auf dem Währungs-Button öffnen Enter, Leertaste oder die Pfeiltasten die Liste, in der ein getippter Buchstabe zu einer Währung springt („u“ zu USD). Das Symbol ist `aria-hidden`, und ein visuell verstecktes „Amount in US dollars“ ist über `aria-describedby` verknüpft. Ein Screenreader hört die Währung also einmal zusammen mit dem Feld statt eines verirrten Dollarzeichens.

## Solltest du für Geld lieber den Number Input nehmen?

Nimm den Number Input, wenn Leute einen Wert schrittweise ändern, und den Currency Input, wenn sie einen Betrag neu eintippen. Der [Number Input](https://wingo-ui.com/components/number-input) nimmt ebenfalls eine Prop `currency` und formatiert mit Intl, arbeitet aber andersherum: Im Ruhezustand zeigt er `$125,000`, beim Fokus wird daraus die reine Zahl zum Bearbeiten. Er ergänzt Stepper-Buttons, die beim Gedrückthalten wiederholen, das Mausrad und Home / End, um zu min und max zu springen. Das passt zu einer Menge, einem Budget oder einem Preis, den du in Schritten von 1.000 anpasst. Für einen Betrag, den Leute neu eintippen, etwa eine Zahlung, eine Spende oder den Preis eines Inserats, passen die Live-Gruppierung, die Währungsauswahl und die Presets des Currency Input besser.

## Welche Fallen bei Währungsfeldern zeigen sich in Produktion?

Die meisten Geld-Bugs entstehen, wenn der formatierte Text als Daten behandelt wird oder mit rohen Gleitkommazahlen gerechnet wird. Die üblichen:

- **Den formatierten String speichern.** `"$1,234.50"` lässt sich weder summieren noch vergleichen. Speichere die Zahl und den Währungscode als zwei Felder.
- **Gleitkommarechnung mit Geld.** `0.1 + 0.2` ergibt in JavaScript `0.30000000000000004`. Runde vor dem Speichern auf die Nachkommastellen der Währung oder speichere ganzzahlige Untereinheiten. Die number-format-Helfer enthalten `roundTo(0.1 + 0.2, 2)`, das `0.3` liefert.
- **Beim Tippen begrenzen.** Wer `5` bei jedem Tastendruck auf ein Minimum von `10` hochsetzt, macht `50` untippbar. Markier den Wert beim Tippen als ungültig und begrenz ihn beim Blur.
- **Mit `parseFloat` parsen.** `parseFloat("1.234,56")` ergibt `1.234` und `Number("1,234.56")` ergibt `NaN`. Parse mit den Trennzeichen der Locale (`parseNumber(text, locale)`) oder lies das versteckte Feld, das immer einen Dezimalpunkt hat.
- **Mit undefinierter Locale formatieren.** `new Intl.NumberFormat()` nimmt auf dem Server die Sprache des Servers und im Browser die des Browsers. `1,234.5` und `1.234,5` passen dann nicht zusammen, und die Hydration scheitert. Übergib eine Locale oder umschließ die App mit `LocaleProvider` aus `@/hooks/use-locale`.
- **Beim Währungswechsel umrechnen.** Wer in einem Formular die Währung wechselt, korrigiert meist nur eine falsche Auswahl. Behalte den Betrag und lass die Person ihn bearbeiten.

Für Rechnungen, bei denen jeder Zeilenbetrag in eine Mehrwertsteuersumme fließt, zeigt unser [Guide zur Mehrwertsteuerberechnung für e-Factura](https://wingo-ui.com/de/blog/e-factura-vat-calculation-javascript) das Runden pro Steuersatz. Das Geldfeld ist eines von vielen Eingabefeldern in unserem [Guide zu React-Formularkomponenten](https://wingo-ui.com/de/blog/react-form-components-guide), und weitere Deep Dives zu einzelnen Komponenten findest du unter [Komponenten-Guides](https://wingo-ui.com/de/blog/category/components).

## Wie installierst du den Currency Input?

Führ `npx wingo-ui@latest add currency-input` aus. Der Befehl kopiert den Currency Input und die kostenlosen Teile, auf denen er aufbaut (Field, Select, Button und die Helfer number-format, use-locale und motion), und installiert die npm-Pakete, die sie importieren, etwa `motion`, `lucide-react` und `vaul` für das Sheet auf dem Smartphone. Currency Input und Number Input gehören zu [Wingo UI Pro](https://wingo-ui.com/de/pricing), also meld dich zuerst mit `npx wingo-ui@latest login` an; `npx wingo-ui@latest add number-format` allein ist kostenlos.

## Komponenten in diesem Artikel

- [Currency Input](https://wingo-ui.com/components/currency-input) (Pro): A React currency input: a money field formatted per locale as you type, with an optional currency selector and quick amount presets. Installation: `npx wingo-ui@latest add currency-input`
- [Number Input](https://wingo-ui.com/components/number-input) (Pro): A React number input to type or step values: steppers with hold to repeat, min, max and step, and Intl formatting for money and units. Installation: `npx wingo-ui@latest add number-input`
- [Number format](https://wingo-ui.com/components/number-format) (Free): Locale-aware number helpers: cached Intl formatting, parsing what people type, step math and currency affixes. Installation: `npx wingo-ui@latest add number-format`

## Häufige Fragen

### Wie formatiere ich einen Currency Input in React?

Halte den Text im State, formatiere ihn bei jeder Änderung neu mit den Intl-Trennzeichen der Locale und setz den Cursor zurück, indem du die Ziffern davor zählst und ihn im neuen Text hinter dieselbe Anzahl setzt. Speichere die geparste Zahl getrennt und füll die Nachkommastellen erst beim Blur auf.

### Warum springt der Cursor in meinem Währungsfeld ans Ende?

Wenn onChange einen neuen String mit einem hinzugefügten oder entfernten Tausendertrennzeichen schreibt, kann der Browser die alte Cursorposition nicht darauf abbilden und setzt den Cursor ans Ende. Zähl die Ziffern vor dem Cursor, formatiere neu und ruf dann in einem useLayoutEffect setSelectionRange hinter derselben Ziffernzahl auf.

### Gibt es einen shadcn Currency Input?

Nicht in der offiziellen Komponentenliste von shadcn/ui, Stand Oktober 2026. Dort gibt es Input und Input Group, aber keinen Währungs- oder Zahlen-Input. Eine verbreitete Abkürzung ist ein Input mit type="number" und einem Dollar-Icon in einer Input Group. Das bringt dir weder Gruppierung noch Locale.

### Sollte ich type="number" für ein Geldfeld in React nehmen?

Nein. Ein Number Input kann weder Tausendertrennzeichen noch ein Währungssymbol zeigen, sein Wert ist ein leerer String, solange der Text ungültig ist, und das Mausrad kann ihn aus Versehen ändern. Nimm ein Textfeld mit inputMode="decimal" und parse den Text selbst.

### Wie speichere ich einen Geldbetrag?

Speichere die Zahl und den ISO-4217-Währungscode als zwei Felder, nie den formatierten String. Viele Teams speichern in der Datenbank ganzzahlige Untereinheiten (Cent), um Gleitkommarechnung zu vermeiden. Behältst du in JavaScript Nachkommastellen, runde vor dem Speichern auf die Nachkommastellen der Währung.

---

Quelle: https://wingo-ui.com/de/blog/react-currency-input
