Currency input — Migrating
Migrating from 0.1.x
Section titled “Migrating from 0.1.x”Two props swapped names in 0.2.0, so that this input emits its value through onChange like every
other input in the suite:
| 0.1.x | 0.2.0 |
|---|---|
onValueChange(value, meta) | onChange(value, meta) |
onChange(event) (DOM) | onNativeChange(event) |
npx @rxova/codemod currency-on-change ./srcDo run the codemod rather than a find-and-replace. The two renames have to happen in one pass: doing
onValueChange → onChange first and onChange → onNativeChange second walks the value handler
through both steps and silently lands it on the native prop.
onValueChange remains as a deprecated compatibility alias and still fires — with a development
warning — so a codebase can migrate one call site at a time.
Why: every other input in the suite emits a plain value from onChange, and this package’s own
README has said so since before this component existed. It was the only one where onChange meant
the DOM event and the value arrived under a different name, which is the sort of inconsistency that
costs a reader more than it ever cost us to keep.
Migrating from react-currency-input-field
Section titled “Migrating from react-currency-input-field”The two libraries solve the same problem differently. react-currency-input-field derives a
separator from one probe and then applies that separator while rebuilding the editable value;
this package delegates each complete idle value to Intl and uses formatToParts() only to parse
the user’s locale-specific input.
Prop mapping
Section titled “Prop mapping”react-currency-input-field | @rxova/react-intl-currency-input |
|---|---|
intlConfig={{ locale, currency }} | locale + currency (top-level props) |
groupSeparator / decimalSeparator | (derived from the locale — remove them) |
prefix / suffix | (derived from the currency — remove them) |
decimalScale | maximumFractionDigits |
fixedDecimalLength | minimumFractionDigits + maximumFractionDigits |
allowNegativeValue | allowNegative |
step | step |
transformRawValue | transformRawValue |
value (string) | value (number | null) |
onValueChange(value, name, values) | onChange(value, meta) — value is a number | null |
Before
Section titled “Before”import { useState } from 'react'import CurrencyInput from 'react-currency-input-field'
function BeforeMigration() { const [value, setValue] = useState<string | undefined>()
return ( <CurrencyInput intlConfig={{ locale: 'bg-BG', currency: 'EUR' }} groupSeparator=" " decimalSeparator="," decimalScale={2} value={value} onValueChange={setValue} /> )}import { useState } from 'react'import { CurrencyInput } from '@rxova/react-intl-currency-input'
function AfterMigration() { const [value, setValue] = useState<number | null>(null)
return <CurrencyInput locale="bg-BG" currency="EUR" value={value} onChange={setValue} />}What changes for the better
Section titled “What changes for the better”- Bulgarian grouping is correct. A hardcoded
groupSeparator=" "uses an ASCII space and groups below 10000. Version 4.0.6’s locale probe uses1000.1; Bulgarian intentionally emits no group part for that value, so the derived separator is empty. Here the non-breaking separator and the “only above 9999” threshold come fromIntl/CLDR automatically. - The value is a number. No more parsing a formatted string back into a number before you submit.
- Fewer props. Separators, prefix/suffix, and fraction digits default from the locale and currency.
- Live formatting with a stable caret. Like
react-currency-input-field, this formats as you type; the caret is anchored to the digit you typed rather than the character index, so grouping changes never move it. Prefer no caret logic at all?formatMode="blur"edits a plain number while focused and formats on blur. - Native digits round-trip. Arabic and other numbering systems are mapped through
Intlrather than an ASCII-only parser.
What to double-check
Section titled “What to double-check”- Your change handler is now
onChangeand receives anumber | null, not a string. Update anything that did string work on it. - If you relied on a custom separator that did not match the locale, switch to the correct
localeinstead. - Abbreviations such as
1k, arbitrary prefixes/suffixes, andcustomInputare intentionally not supported. They make the field a generic numeric mask rather than a locale-defined currency input. UsetransformRawValuefor application-specific cleanup before parsing.