InputMask of react-input-mask doesn't work with setValue of react-hook-form

180 Views Asked by At

I'm trying to extract infos from an api with useEffect and set the values of the inputs with those infos with setValue. I'm using react-hook-form too

useEffect(() => {
const getData = async () => {
  const response = await api.get(`/clientes/${id}`)

  if (response.status === 200) {
    setValue('name', response.data.name)
    setValue('email', response.data.email)
    console.log(response.data.phone) // (51) 99999-9999
    setValue('phone', response.data.phone)
  }
}

getData()
}, [id, setValue])

But when the component generates the value of 'phone' remains empty. I'm using InputMask of react-input-mask, here's my input:

<label>
  Telefone
  <InputMask
    mask="(99) 99999-9999"
    maskChar="_"
    type="text"
    id="celular"
    {...register('celular')}
  />
  {errors.celular && (
    <EditClientFormError>
      {errors.celular.message}
    </EditClientFormError>
  )}
</label>

I tried to format the data back to a number, but it didn't work either

useEffect(() => {
    const getData = async () => {
      const response = await api.get(`/clientes/${id}`)
    
      if (response.status === 200) {
        setValue('name', response.data.name)
        setValue('email', response.data.email)
    
        const numberWithoutMask = response.data.phone.replace(/\D/g, '')
        const number = parseInt(numberWithoutMask, 10)
        console.log(number) // 51999999999
    
        setValue('phone', number)
      }
    }
    
    getData()
  }, [id, setValue])

I imagine that the problem is with InputMask, but it's the only effective way I know to mask an input. Does anybody know how can I fix this?

1

There are 1 best solutions below

1
On

In React, state updates are batched together for performance optimization during React event handlers. Automatic batching does not occur in asynchronous operations. Multiple consecutive setValue calls in your async function triggers multiple re-renders, which could lead to issues.

Instead use it like this

useEffect(() => {
  const getData = async () => {
    try {
      const response = await api.get(`/clientes/${id}`);
      if (response.status === 200) {
        setValue({
          name: response.data.name,
          email: response.data.email,
          phone: response.data.phone
        });
      }
    } catch (error) {
      console.error("Error fetching data: ", error);
    }
  };

  getData();
}, [id, setValue]);