useNumericFormatAdapter
Returns adapter props for wiring react-number-format's NumericFormat (prefixes, thousand separators, decimals) to React Hook Form.
useNumericFormatAdapter connects a field to React Hook Form and returns props you spread onto NumericFormat from react-number-format. It's what NumericFormatElement uses internally. It calls useNumberFormatBaseAdapter with the same props, so the wiring is identical; this page covers what matters for amounts and quantities.
Use the element for one-off fields. Reach for the hook when you want a reusable money or quantity field with the currency format, range and messages fixed in one place, or when your form should hold a number rather than a string.
Import
import { useNumericFormatAdapter } from "@piplup/rhf-adapters/react-number-format";Usage
This BudgetField shows $12,500.00-style input, stores a number (or null when empty), and limits the range with its own messages. Try 200 or 75000, then submit.
"use client";import Stack from "@mui/material/Stack";import TextField from "@mui/material/TextField";import { MuiButtonElement } from "@piplup/rhf-adapters/mui-material";import { useNumericFormatAdapter } from "@piplup/rhf-adapters/react-number-format";import { type Control, useForm } from "react-hook-form";import { NumericFormat, type NumberFormatValues } from "react-number-format";type FormValues = { budget: number | null };// Stores a real number (or null) instead of the default numeric string,// and enforces a range with project-specific messages.function BudgetField({ control }: { control: Control<FormValues> }) { const adapter = useNumericFormatAdapter<number | string, FormValues, "budget">({ control, name: "budget", required: true, composeHelperText: true, min: 500, max: 50000, helperText: "Between $500 and $50,000", messages: { required: "Enter a budget", min: "The minimum budget is $500", max: "Budgets over $50,000 need approval", }, transform: { input: (value) => value ?? "", output: (values: NumberFormatValues) => values.floatValue ?? null, }, }); return ( <NumericFormat customInput={TextField} label="Project budget" prefix="$" thousandSeparator decimalScale={2} allowNegative={false} {...adapter} /> );}export default function Page() { const { control, handleSubmit } = useForm<FormValues>({ defaultValues: { budget: null }, }); return ( <form noValidate onSubmit={handleSubmit((values) => alert(JSON.stringify(values, null, 2)))} > <Stack direction="column" spacing={2}> <BudgetField control={control} /> <div> <MuiButtonElement control={control} variant="contained" type="submit"> Submit </MuiButtonElement> </div> </Stack> </form> );}How it works
Stored value is a string by default. The form receives values.value from onValueChange: the number as a string, without prefix, suffix or thousand separators, and with . as the decimal point. Typing $12,500.5 stores "12500.5". An empty input stores "".
Storing a number. Pass transform.output: (values) => values.floatValue ?? null, as in the demo. floatValue is undefined when the input is empty, hence the fallback. Pair it with transform.input: (value) => value ?? "": NumericFormat treats a null value as "not controlled" and keeps showing its last text, so without it reset() to null would not clear the input.
Range checks. min and max work with both storage styles. React Hook Form converts the stored string to a number before comparing, so "12500.5" is checked as 12500.5. Formatting characters never reach the check.
| Key | Default message |
|---|---|
required | Please fill out this field. |
min | Value must be min or later. |
max | Value must be max or earlier. |
The default min/max wording is shared with date inputs, so most money fields set their own messages. minLength and maxLength count characters of the stored string ("12500.5" is 7), not of the formatted text.
Message functions get the limit wrapped in an array: min: (min) => ... receives [500]. Inside a template string that prints as 500, but call number methods on min[0].
Errors and helper text. Set composeHelperText: true when rendering through customInput={TextField}. You then get error and a helperText that shows the error message, or your helperText when valid. Without it, neither prop is returned. Like the base hook, the field ref ends up on the TextField root, so focus-on-error does not reach the input.
Props
Prop
Type
Return value
Prop
Type
useNumberFormatBaseAdapter
Returns adapter props for wiring react-number-format's NumberFormatBase, with your own format function, to React Hook Form.
usePatternFormatAdapter
Returns adapter props for wiring react-number-format's PatternFormat masks (phone numbers, card numbers, codes) to React Hook Form.