s-yadav / react-number-format

React component to format numbers in an input or as a text.
MIT License
3.85k stars 404 forks source link

NumericFormat does not accept ref prop #690

Open vitorbertolucci opened 1 year ago

vitorbertolucci commented 1 year ago

Describe the issue and the actual behavior

The NumericFormat component does not accept a ref prop on v5, but the former default ReactNumberFormat component did.

Describe the expected behavior

I would like to be able to use a ref so I can use NumericFormat as an uncontrolled component. I used to do this with ReactNumberFormat so I did not need to use onValueChange function nor pass the value prop. And I used the ref so I could retrieve the input value and also clear it when needed.

Here is the error when I try to pass a ref to NumericFormat:

Property 'ref' does not exist on type 'IntrinsicAttributes & InternalNumberFormatBase & { thousandSeparator?: string | boolean | undefined; decimalSeparator?: string | undefined; ... 7 more ...; prefix?: string | undefined; } & Omit<...> & Omit<...> & { ...; }'

s-yadav commented 1 year ago

is getInputRef prop not working for you? https://s-yadav.github.io/react-number-format/docs/props#getinputref-elm--void

vitorbertolucci commented 1 year ago

is getInputRef prop not working for you? https://s-yadav.github.io/react-number-format/docs/props#getinputref-elm--void

getInputRef gives a ref for the actual <input> element. I'd like to have a ref to NumericFormat component so I can read its entire state.

I have already come up with an obvious workaround, which is to wrap the NumericFormat in my own custom input component and use it as a controlled component, but until v5 it was possible to get a ref to ReactNumberFormat and use it as an uncontrolled component.

s-yadav commented 1 year ago

Ohh its a functional component now, so you can’t get the internal state now. Btw, whats the usecase of getting internal values. If you require more fine grained control on the behaviour, you may use the hook useNumericFormat. You can refer the customisation doc. https://s-yadav.github.io/react-number-format/docs/customization

DavidJayBrady commented 6 months ago

Just spent too long struggling to make this play nice with react-hook-form in a Controller. I was getting this warning using NumericFormat inside the Controllers render

Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Thanks @vitorbertolucci for mentioning the workaround which was unfortunately not so obvious to me. Here is how I got it working in case other people need it

const NumericFormatWrapper = React.forwardRef(({ id, ...rest }, ref) => {
  return (
    <NumericFormat
      id={id}
      getInputRef={ref}
      {...rest}
      className="<tailwind classes>"
    />
  );
});

You can also make your own custom input component and pass that to NumericFormat if you want, the hard part was realizing NumericFormatneeded a wrapper to make it work as expected.

Also in case it's useful for others, here is how I'm using it inside a react hook form controller

const id = useId();
...
        <Controller
          name={formName}
          control={control}
          render={({ field }) => <NumericFormatWrapper id={id} {...field} {...rest} />}
        />
tygas commented 21 hours ago

or maybe you can just exclude ref from field.

 <Controller
        name={name}
        control={control}
        render={({ field }) => {
        const { ref: _, ...restField } = field 
        return (
            <NumericFormat
              {...restField}
              {...props}
              getInputRef={ref}
              maxLength={7}
              customInput={Input}
              customSuffix={customSuffix}
            />
          )
        }}
      />