Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controlled component with hook #552

Closed
sajcics opened this issue Sep 19, 2021 · 10 comments
Closed

Controlled component with hook #552

sajcics opened this issue Sep 19, 2021 · 10 comments

Comments

@sajcics
Copy link

sajcics commented Sep 19, 2021

Describe the bug
I am trying to use 'react-imask' in my controlled component where I need to manage state outside the component... but I found three issues:

  1. onChange on input triggers max three times
  2. there is no possible option to define value inside useIMask hook (which will be nice so I can avoid defining value and onChange property on input itself)
  3. when I define some initial value to component, and delete the value inside the input, the first number always stays even when input should be empty

To Reproduce
https://codesandbox.io/s/currying-shadow-hbzsr?file=/src/App.js

for first issue:

  1. try to insert 4 values in input (you will see only 3 onChange console.logs)

for third issue:

  1. try to delete all values in input
  2. input will have value '1' as default and can not be deleted

Expected behavior
for first issue - I am expecting to trigger every onchange when value is changed
for second - I am expecting to avoid any value and onChange definitions on tag and to have everything in useIMask hook where I will define a initial value and listener, and then use useEffect to update input reference with updateValue().. but now I can not define any initial value for hook (at least I can not see it in documentation)
for third - input to be empty

I am more for second option to have everything handled via input reference instead to define onChange and value properties on tag. Or at least update documentation how to use it correctly to have controlled component with hook.

Environment:

  • OS: Linux 18.04
  • Browser Chrome
  • Version 93.0
  • IMask version 6.2.2
  • Framework/plugin version if used - typescript

Additional context
Maybe I am doing something wrong here, but it will be nice to have better documentation for hook and for case when input is controlled component.

@dziul
Copy link

dziul commented Oct 6, 2021

My case, I ended up using imask directly instead of react-imask.

...
const [value, setValue] = React.useState('')
const innerRef = React.useRef<HTMLInputElement>(null)

React.useEffect(() => {
      if (innerRef.current && maskConfig) {
        maskRef.current = IMask(innerRef.current, maskConfig)

        maskRef.current.on('accept', () => {
          setValue(maskRef.current?.value as string)
          if (onUnmaskedValueChange)
            onUnmaskedValueChange(maskRef.current?.unmaskedValue || '')
        })
      }

      return () => {
        maskRef.current?.destroy()
        maskRef.current = null
      }
    }, [maskConfig, onUnmaskedValueChange])

    React.useEffect(() => {
      setValue((maskRef.current?.value as string) || '')
    }, [maskRef.current?.value])


const handleChange: React.ChangeEventHandler<HTMLInputElement> = event => {
      if (!maskConfig) setValue(event.target.value)
      if (onChange) onChange(event)
}

...

so i avoid the message error

Element value was changed outside of mask. Syncronize mask using `mask.updateValue()` to work properly.

Since every time the value is changed a new instance of IMask is generated

@Enteleform
Copy link

Similar issue here. I'm forwarding a callback to allow components to update the IMask instance:

return {
  set_Value(value:(string|number)){
    iMask.value = `${value}`
    iMask.updateValue()
  }
}

I've tried every possible combination of updates after checking out input.js (_value, masked.value updateControl(), etc.) but could not manage to avoid this error.

@uNmAnNeR What is the proper way to update an IMask instance programatically without running into this error?

@uNmAnNeR
Copy link
Owner

should be fixed in 83f8ce8

@dominikkurbiel
Copy link

@uNmAnNeR maybe you can provide some examples how to have controlled input, and how to provide initial value?

@khmelevskii
Copy link

yes, can you please provide example

@vinderman
Copy link

+, need example

@vendramini
Copy link

vendramini commented Jul 13, 2023

I tried to make it work as a controlled component with a defaultValue but I failed too... However, I ended up with a solution that has been working good so far (although I'm not sure if it's correct). Just add a key property as the same as your value and the component will be re-rendered. By doing that, we don't lose any built-in functionality that conflicts when we set value manually.

const currentValue = value?.format(format);

<IMaskInput
        mask={Date}
        key={currentValue} // <--- here
        defaultValue={currentValue}
        pattern={format}
        format={(value: unknown) => dayjs(value as string).format(format)}
        parse={value => dayjs(value, format).toDate()}
        placeholder={placeholder}
        lazy={false}
        overwrite
        unmask={'typed'}
        className={clsx('form-control', {'is-invalid': isInvalid})}
        blocks={blocks}
        onAccept={(acceptedValue) => {
          onChangeDate(acceptedValue ? dayjs(acceptedValue as unknown as Date) : null);
        }}
        onClick={() => setShow(!show)}
      />

@cristiano-belloni
Copy link

should be fixed in 83f8ce8

This is not fixed.

@isaacebhodaghe
Copy link

should be fixed in 83f8ce8

This is not fixed.

@cristiano-belloni Were you able to find a work around ?

@rdebeasi
Copy link

I've put together a small proof of concept: https://codesandbox.io/p/sandbox/controlled-react-imask-5llklh

I'm not sure if this is exactly right, but it's at least a start! If you have thoughts or suggestions, feel free to join the conversation in #1100.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests