mrkeyoor.com_
Wed 23 Sept 00:33 UTC
npmWeb Frontendupdated 18 Sept 2026

react-number-format review

react-number-format 5.4.5 is a React input formatter with caret management. `NumericFormat` handles grouping, decimal scales, prefixes, suffixes, and numeric-string state; `PatternFormat` places digits into fixed masks; `NumberFormatBase` supports custom formatting rules. It can also render formatted text, but its harder job is keeping selection and deletion sensible while a user edits punctuation around digits. The 5.4.5 release fixes `defaultValue` changes failing to call `onValueChange` and deletion of a negative sign when a prefix has more than 1 character. It formats and restricts input; it does not verify money, phone numbers, or card data.

Verdict

Our react-number-format 5.4.5 install took 1.2 seconds, produced a 9.7 KB gzipped browser bundle, and had no audit findings. Install it when caret-correct React editing is the requirement; use `Intl.NumberFormat` for display and a domain validator for the meaning of the digits.

We installed it

Lab card: what happened when we installed react-number-formatScreenshot of react-number-format documentation
Install✓ · 1.2s4 packages on disk · 8 MB
ImportESM import works · require() works · CommonJS package
Browser9.7 KBgzipped (26.4 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does react-number-format install cleanly?

Yes. In a fresh container with an empty cache, npm install react-number-format finished in 1 seconds, leaving 4 packages and 8 MB on disk. npm audit reported no known vulnerabilities.

How much does react-number-format add to a browser bundle?

9.7 KB gzipped (26.4 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does react-number-format work with both ESM and CommonJS?

Yes. Both import 'react-number-format' and require('react-number-format') worked in Node 22 in our run. The package is published as CommonJS.

Does react-number-format include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

react-number-format or react-imask: which should you use?

react-imask: Choose react-imask when one masking system must cover dates, text patterns, numbers, and custom mask definitions. Our react-number-format 5.4.5 install took 1.2 seconds, produced a 9.7 KB gzipped browser bundle, and had no audit findings.

When should you not use react-number-format?

You only display numbers: Intl.NumberFormat handles locale-aware output without a React input dependency or caret engine

API stability4/5Version 5 splits the public API into `NumericFormat`, `PatternFormat`, and `NumberFormatBase`, with typed formatter functions and hooks underneath. The 5.4 line has kept that structure, but small releases still change observable callback and caret behavior; 5.4.0 made `onValueChange` fire for prop changes, and 5.4.5 fixed a missed `defaultValue` callback. The v4 migration renamed exports and removed `customNumerals`, so major upgrades need field-level tests.
Docs5/5The official version 5 site has separate prop references for numeric and pattern formats, live demos, a migration page, a customization guide, and a quirks page that describes the 3 value representations and 2 callback sources. It also states when `valueIsNumericString` is required, why native length props mislead, and how mobile input types affect separators. A few examples have rough prose, but the difficult behavior is documented rather than hidden.
Maintenance4/5Version 5.4.5 was published on March 22, 2026, and the repository was pushed the same day. That release fixed two specific input regressions, while 5.4.3 added React 19 to the peer range and 5.4.0 replaced the old Karma setup with Vite, jsdom, and React Testing Library. GitHub reports 229 open issues and pull requests, which is a meaningful queue for a library maintaining browser, selection, mobile, and React compatibility.
Ecosystem5/5npm recorded 5,130,174 downloads in the latest measured week, and the repository has 4,098 stars. The package declares React and React DOM peers from 0.14 through 19, ships TypeScript declarations, has 0 runtime dependencies, and accepts custom input components such as Material UI fields. It remains React-specific and leaves schema validation, locale selection, and form-library wiring to the application.

Use it if

  • A React field must insert grouping or a fixed digit pattern without throwing the caret to the end on each edit
  • You want to keep an unformatted numeric string in controlled state while showing prefixes, suffixes, separators, or fixed decimals
  • Your form needs `isAllowed` to reject an edit before the displayed value changes
  • A design-system input can be passed as a stable `customInput` component reference
Skip it if

Setup reality

We installed react-number-format 5.4.5 in 1.2 seconds. The install left 4 packages using 8 MB on disk; the package itself was 280 KB unpacked, with 0 direct dependencies, 2 peer dependencies, bundled TypeScript declarations, and no npm audit findings. require() and ESM import both worked on Node 22.

The 2 peers are React and React DOM, accepted from React 0.14 through 19. The package is CommonJS-first, also publishes an ESM build, and has no exports map. Our full browser import built to 26.4 KB minified and 9.7 KB gzipped. There are no credentials, config files, or native builds.

Controlled fields should usually store the value string from onValueChange and pass valueIsNumericString. The callback also supplies formattedValue, floatValue, and a source of event or prop; it can run after a prop update or blur, so it is not a renamed native onChange. Large or exact decimals should stay as strings because floatValue can lose precision or use exponential notation.

Formatting happens after native input length checks, which is why the docs say minLength and maxLength do not impose the expected digit limit. Use isAllowed, allow an empty value so deletion still works, and test paste plus caret movement. For mobile fixed patterns, the docs recommend type="tel"; decimal input usually needs type="text" so the keyboard can expose a separator.

Patterns

Store currency digits as a string edit-currency-value

import {NumericFormat} from 'react-number-format';

<NumericFormat
  value={amount}
  valueIsNumericString
  onValueChange={({value}) => setAmount(value)}
  thousandSeparator=","
  decimalScale={2}
  fixedDecimalScale
  prefix="$"
/>

The prefix labels the field but does not select a currency or perform conversion. Keep the unformatted string when decimal precision matters.

Read all three value representations inspect-value-forms

<NumericFormat
  onValueChange={({formattedValue, value, floatValue}, sourceInfo) => {
    console.log({formattedValue, value, floatValue, source: sourceInfo.source});
  }}
/>

`floatValue` can lose precision or use exponential notation. `value` is the safer state form for long identifiers and exact decimal input.

Accept comma decimal input format-european-decimals

<NumericFormat
  value={amount}
  valueIsNumericString
  thousandSeparator="."
  decimalSeparator=","
  allowedDecimalSeparators={[',', '.']}
  onValueChange={({value}) => setAmount(value)}
/>

Set `valueIsNumericString` when an unformatted string is paired with `.` as the grouping separator, or digits in format props can be misread.

Reject an edit above a limit limit-numeric-range

<NumericFormat
  value={quantity}
  decimalScale={0}
  allowNegative={false}
  isAllowed={({floatValue}) => floatValue == null || floatValue <= 1000}
  onValueChange={({value}) => setQuantity(value)}
/>

Allow `floatValue == null` so the user can clear the input. Returning false blocks both the edit and its value callback.

Place phone digits into a fixed pattern format-phone-pattern

import {PatternFormat} from 'react-number-format';

<PatternFormat
  format="+1 (###) ###-####"
  mask="_"
  type="tel"
  value={phoneDigits}
  valueIsNumericString
  onValueChange={({value}) => setPhoneDigits(value)}
/>

This pattern restricts positions and formats digits. It does not prove that the number exists or validate a country numbering plan.

Group a 16-digit card input mask-card-digits

<PatternFormat
  format="#### #### #### ####"
  mask="_"
  type="tel"
  value={cardDigits}
  valueIsNumericString
  onValueChange={({value}) => setCardDigits(value)}
/>

The 16-place mask excludes other card lengths and performs no Luhn check. Payment data also needs the controls required by your processor and compliance scope.

Render a read-only formatted amount render-formatted-text

<NumericFormat
  value="1234567.5"
  valueIsNumericString
  displayType="text"
  thousandSeparator
  prefix="$"
  decimalScale={2}
  fixedDecimalScale
/>

For display-only locale output, `Intl.NumberFormat` avoids the 9.7 KB gzipped input package and handles currency conventions by locale.

Use a Material UI text field wrap-design-system-input

import {TextField} from '@mui/material';

<NumericFormat
  customInput={TextField}
  label="Budget"
  value={budget}
  valueIsNumericString
  thousandSeparator
  onValueChange={({value}) => setBudget(value)}
/>

`customInput` expects a component reference. The props guide says an inline function such as `() => <TextField />` will not work.

Capture the underlying input reference focus-formatted-input

const inputRef = useRef(null);

<NumericFormat
  getInputRef={(element) => { inputRef.current = element; }}
  thousandSeparator
/>

inputRef.current?.focus();

With `customInput`, the referenced value depends on that component's ref contract and may not be a native HTML input.

Separate user edits from prop updates filter-prop-updates

<NumericFormat
  value={amount}
  valueIsNumericString
  onValueChange={({value}, {source}) => {
    if (source === 'event') setAmount(value);
  }}
/>

Since 5.4.0, `onValueChange` fires for prop-driven changes too. Its source is `event` or `prop`, and the callback can also run on blur.

Format a numeric string without rendering format-outside-jsx

import {numericFormatter} from 'react-number-format';

const label = numericFormatter('1234567.5', {
  thousandSeparator: ',',
  decimalScale: 2,
  fixedDecimalScale: true,
  prefix: '$',
});

Pass unformatted digits as the first argument. Use `Intl.NumberFormat` when the locale, rather than input editing rules, should choose the output.

Block decimal and negative input accept-whole-numbers

<NumericFormat
  value={count}
  valueIsNumericString
  decimalScale={0}
  allowNegative={false}
  onValueChange={({value}) => setCount(value)}
/>

The quirks guide recommends `decimalScale={0}` for whole numbers. Native `maxLength` does not reliably limit digits after formatting, so use `isAllowed`.

Alternatives

PackageRegistryPick it when
react-imasknpmChoose react-imask when one masking system must cover dates, text patterns, numbers, and custom mask definitions.
react-currency-input-fieldnpmChoose react-currency-input-field for a narrower currency input with abbreviations and fewer low-level caret APIs.
cleave.jsnpmChoose Cleave.js when formatting must work outside React and its predefined credit-card, phone, date, and numeral blocks cover the field.
numeralnpmChoose numeral for parsing and display formatting in non-input code, after checking whether its older release cadence fits the project.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.