react-currency-input-field: a currency input with no runtime dependencies
React component for an input field
At a glance
- What is it?
- react-currency-input-field is a React input component for currency and numbers, with grouping separators, prefix and suffix, abbreviations such as 1k for 1,000, Intl locale configuration, keyboard stepping and decimal limits. It is written in TypeScript and ships with no third party runtime dependencies at all.
- Who is it for?
- react-currency-input-field suits a team that needs a money input that behaves like the one in a payment flow rather than a bare number field, because it handles grouping, decimals, abbreviations and locale formatting in one small dependency free package that costs about three kilobytes gzipped.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A focused input component
react-currency-input-field is a React component for an input field, written in TypeScript with type support, and the package description is precise about what it does: a React input component for formatting currency and numbers.
The feature list explains what that means in practice. It supports abbreviations, so typing 1k yields 1,000 and 2.5m yields 2,500,000. It supports a prefix and a suffix, which is how you put a currency symbol or a unit next to the number. It inserts group separators automatically. It accepts an Intl locale configuration. The arrow up and arrow down keys step the value. And decimals can be allowed or disallowed.
Two details stand out for an adopter. The first is the dependency count: zero runtime dependencies, meaning it does not depend on any third party package except for development. The second is the bundle size, quoted as 7.6 kilobytes minified and 3.1 kilobytes minified and gzipped, with a link to a bundle size report.
For a component that most applications add once and use in one or two places, that is the right shape. There is no formatting library to keep up to date, no peer dependency to reconcile, and nothing to break when another package changes its own dependency tree.
Abbreviations, separators and locale
The formatting behaviour is where a currency field earns its place, and the props table shows how much of it is configurable.
Abbreviations are the shorthand input parsing, and they can be turned off with a prop if you do not want them. The default is to allow them.
The separators are configurable in three ways. The decimal separator character defaults to the locale default, and it cannot be numeric or match the group separator, which is a sensible constraint since a decimal separator that is a digit would be ambiguous. The group separator character also defaults to the locale, cannot be numeric, and can be suppressed entirely with a prop, which keeps a value as 1000 instead of formatting it as 1,000. There is also a fixed decimal length prop, which forces the value to always display with a specified number of decimals when the field loses focus.
The locale itself comes from an intlConfig prop, and the table describes it as the locale configuration for the Intl.NumberFormat call, taking the locale, the currency and the style. So the component delegates the actual formatting to the platform's own internationalisation API rather than shipping its own rules, which is why the separator defaults are described as locale defaults rather than fixed characters.
The remaining formatting props are the decimal scale, which pads or trims decimals on blur to a specified length, and the decimals limit, which caps how many fractional digits the user can type, defaulting to two.
Values, blur behaviour and the rest of the props
The value handling follows the usual React split between controlled and uncontrolled, with the default value prop for the uncontrolled case and the value prop for the controlled one, both accepting a number or a string.
The change callback is the part with the subtlety. The onValueChange callback receives the value, the name and the values object, and the formatValueOnBlur prop controls whether the callback fires on blur events, with the default being true. So the formatted value is reported when the user leaves the field rather than on every keystroke, which is usually what a form wants, and the prop exists for the cases where it is not.
Other props cover the ordinary needs. There is a class name for styling, an id forwarded to the rendered input, a disabled flag, and a customInput prop that takes a React element type and lets you render something other than the native input, defaulting to input.
That customInput escape hatch is the answer to the objection that the component is too opinionated. It lets you keep the formatting behaviour while supplying your own element, for example one from a component library, though the props of that element are then your problem rather than the component's.
The usage example in the README shows the shape of a typical use, with an id, a name, a placeholder, a default value, a decimals limit and a callback that logs the three arguments.
Installing it and the demo
Installation is the usual three lines, one per package manager.
npm install react-currency-input-field
yarn add react-currency-input-field
pnpm add react-currency-input-fieldThe usage example is short.
import CurrencyInput from 'react-currency-input-field';
<CurrencyInput
id="input-example"
name="input-name"
placeholder="Please enter a number"
defaultValue={1000}
decimalsLimit={2}
onValueChange={(value, name, values) => console.log(value, name, values)}
/>;There is a hosted demo to play with, and the examples directory in the source tree covers more patterns, including implementation details and validation helpers.
The README also carries a section on formatting values for display, which is the piece that separates display formatting from the stored value. A currency field has two jobs, showing the user a formatted number and telling the application what the number is, and a component that conflates the two causes subtle bugs when the application stores the formatted string.
The changelog section at the end of the README is worth checking if you are upgrading, since the readme also has an announcement section for the 4.0.0 release.
Packaging, dual builds and package verification
The package metadata shows more care than most component packages manage, and it is the part worth copying if you publish your own.
The build produces two module formats. The exports map has separate import and require conditions, each pointing at its own types file and its own JavaScript, so an ES module consumer and a CommonJS consumer both get the right entry point, with the main and module fields pointing at the same two builds and a top level types field for older tooling.
The published files list includes the dist directory, the component sources as TypeScript and TSX, and the index file, with the test directories excluded. Shipping the component sources alongside the build means a consumer can read the implementation of the component they depend on, and lets a bundler process the TypeScript directly if it prefers.
The scripts are the other telling part. The build runs the JavaScript bundler and then the type build, which itself runs the compiler and then a script that produces the ES module type declarations. The test script sets the locale explicitly for the test run, the lint step allows no warnings at all, and there is a check script that runs the format check, the lint, the type check and the tests together.
And then there is the package verification. A publint script and an are the types wrong script are run together by a verify-package target, and both are tools that check a package before publishing: one for the packaging conventions, one for whether the type declarations match the exports. Catching that in your own pipeline is far better than having a consumer report it.
Testing, tooling and maintenance
The repository carries both unit and browser test configurations, with a Jest configuration for the unit tests and a Playwright configuration for the browser, and the test command sets the language to en_GB so the locale defaults under test are deterministic.
The rest of the tooling is a well equipped JavaScript project. The build is esbuild with a small configuration file, the type declarations are produced by the compiler plus a script that handles the ES module specifics, and formatting is Prettier with linting by ESLint. Husky runs the hooks, and lint-staged configures what happens to each kind of file on commit, so a change to a TypeScript file is linted and formatted and a change to a JSON, Markdown or YAML file is formatted.
Releases are automated with semantic-release, and there is a matching commit message convention enforced by a commitlint configuration and a release configuration file, so the version number and the changelog are derived from the commit history rather than maintained by hand.
The release tags are v4.0.14 from 2026-10-11, v4.0.13 from 2026-10-10 and v4.0.12 from 2026-10-01, and the last push was on 2026-10-18. So the project ships patch releases frequently, and the patch level is carrying most of the work, which is what you want from a component whose API is stable.
The licence is MIT, with the LICENSE file at the root of the repository, and the project also ships agent instruction files and a changelog.
Editorial conclusion
react-currency-input-field suits a team that needs a money input that behaves like the one in a payment flow rather than a bare number field, because it handles grouping, decimals, abbreviations and locale formatting in one small dependency free package that costs about three kilobytes gzipped. It is the wrong choice if you need a fully custom control, since the component has a fixed input shape with a custom input escape hatch rather than a headless design, and the wrong choice if your application standardises on a form library whose own currency field already does the job. Verify first which locale the Intl configuration targets and that its default separator matches what your users expect, decide whether abbreviations should be enabled for your market, and read the blur behaviour props before you rely on the change callback firing only on blur.
Frequently asked questions
What does react-currency-input-field do?
It is a React input component for currency and numbers that supports abbreviations such as 1k for 1,000, a prefix and a suffix, automatic group separators, an Intl locale configuration, keyboard stepping with the arrow keys, and configurable decimal limits.
Does react-currency-input-field have any runtime dependencies?
No. The feature list states that it has zero runtime dependencies, meaning it does not depend on any third party package except for development, and the bundle size is given as 7.6 kilobytes minified and 3.1 kilobytes gzipped.
How do I control the number formatting and the locale?
Through the intlConfig prop, which holds the locale configuration for the Intl.NumberFormat call, plus props for the decimal and group separator characters, a prop to suppress group separators entirely, and props for the decimal scale, the decimals limit and a fixed decimal length on blur.
Can I use a custom element instead of the native input?
Yes. The customInput prop takes a React element type and defaults to input, so you can render your own component while keeping the formatting behaviour.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cchanxzy-react-currency-input-field)Was this useful?