imaskjs: React IMaskInput's onChange listener called inconsistently

I am building an app using react-imask and the <IMaskInput> component. With the following props being passed:

<IMaskInput
    id={id}
    name={name}
    className={className}
    value={value}
    onChange={onChange}
    onBlur={onBlur}
    onFocus={onFocus}
    type="text"
    ref={ref}
    masktype={type}
    mask={Number}
    thousandsSeparator=","
/>

When typing into the input, the first character does not trigger the onChange listener to be called. The second and third characters do trigger onChange. And then any other characters input again do not trigger the listener. (Once there is a thousandsSeparator onChange doesn’t get called anymore.)

If I remove thousandsSeparator: ',' the first character still does not trigger the onChange listener to be called. However, all subsequent characters do trigger onChange.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 16 (7 by maintainers)

Most upvoted comments

@uNmAnNeR @grantiverson the problem with the solution provided above is that onAccept will be triggered even when the input wasn’t manually changed but received a prop value, which will then trigger onChange as well. (What doesn’t happen with onChange, because well, the input wasn’t really changed).

In many cases this isn’t a problem, in situations like me though, the onChange triggers also other events like form.onFieldChanges (when using it within a form component), which is giving me some headaches.

It’d be great to have something similar to onChange, like an onAccept but that’s only triggered when the field is manually changed, not when the component was initialized with a value different than undefined.

@icaroponce @felicandalc a bit outdated but seems like it’s possible to determine if the change was triggered by user or not by checking the last parameter of onAccept(value, ref, event) the last parameter event is not null if the change was triggered by user input. I will close this issue for now but you can reopen it again if more things are still need to be clarified/fixed.

Hi, I managed to somehow get the onChange to work. here my example using react-datepicker

I run the onChange I receive from Props and pass a mock onchange event to it.



  return <>
    <IMaskInput
      mask={`d/m/Y`}
      autofix={true}
      lazy={false}
      blocks={{
        d: {mask: IMask.MaskedRange, placeholderChar: 'D', from: 1, to: 31, maxLength: 2},
        m: {mask: IMask.MaskedRange, placeholderChar: 'M', from: 1, to: 12, maxLength: 2},
        Y: {mask: IMask.MaskedRange, placeholderChar: 'Y', from: 1900, to: 2022, maxLength: 4}
      }}
      ref={ref}
      onAccept={
        (value: any) => {
          if (!name) return

          let dateSplit = value.split('/')
          let date = new Date(+dateSplit[2], dateSplit[1] - 1, +dateSplit[0])

          if (!isValidDate(date)) return
          if (!rest.onChange) return

          rest.onChange({
              target: {
                value: date
              }
            } as unknown as ChangeEvent<HTMLInputElement>
          )

          return true
        }
      }
      name={name}
      {...rest}
    />
  </>


Here is an example of the behavior I’m seeing: https://codesandbox.io/s/tender-hawking-h7cb3