Criando mascara para input com React e useForm
Fala galera!
Recentemente eu precisei trabalhar com máscara no React com TypeScript e tive alguns problemas ao usar a lib ReactInputMask.
Recebi o Error
Overload 1 of 2, '(props: Props | Readonly<Props>): ReactInputMask', gave the following error. Type '(inputProps: any) => JSX.Element' is not assignable to type 'ReactI18NextChild | Iterable<ReactI18NextChild>'. Overload 2 of 2, '(props: Props, context: any): ReactInputMask', gave the following error.Type '(inputProps: any) => JSX.Element' is not assignable to type 'ReactI18NextChild | Iterable<ReactI18NextChild>'.
Então decidi postar aqui a solução que encontrei utilizando o regex e acredito que poderá ajudá-los em alguma ocasião.
Primeiro vamos criar uma pasta chamada MASKS e dentro dela criaremos um arquivo chamado MASK.TS, para criarmos a função que fará a máscara.
Agora dentro do arquivo mask.ts vamos criar a duas funções que serão nossas mascaras “cnpj, telefone e cep” , no caso do TypeScript, precisaremos passar um type para o parâmetro da nossa função, nesse caso passaremos a tipagem com String ou undefined.
No início da função iremos verificar se existe algum valor dentro do nosso parâmetro, caso não exista daremos um return vazio e sairemos da função, caso exista valor faremos todo o regex até termos o resultado que gostaríamos
export const normalizePhoneNumber = (value: String | undefined) => {
if (!value) return ''
return value.replace(/[\D]/g, '')
.replace(/(\d{2})(\d)/, '($1) $2')
.replace(/(\d{5})(\d)/, '$1-$2')
.replace(/(-\d{4})(\d+?)/, '$1')
}
export const normalizeCnpjNumber = (value: String | undefined) => {
if (!value) return ''
return value.replace(/[\D]/g, '')
.replace(/(\d{2})(\d)/, '$1.$2')
.replace(/(\d{3})(\d)/, '$1.$2')
.replace(/(\d{3})(\d)/, '$1/$2')
.replace(/(\d{4})(\d)/, '$1-$2')
.replace(/(-\d{2})\d+?$/, '$1')
}
export const normalizeCepNumber = (value: String | undefined) => {
if (!value) return ''
return value.replace(/\D/g, "")
.replace(/^(\d{5})(\d{3})+?$/, "$1-$2")
.replace(/(-\d{3})(\d+?)/, '$1')
}
O próximo passo será importa a função onde precisaremos usar a máscara. No meu caso estava usando a lib react-use-form então precisei utilizar a função watch do proprio useForm para conseguir escutar quando esse campo recebe um valor e a função setValue para setar o valor para a mesma variável dentro do useForm.
import {useForm} from 'react-hook-form'
import { normalizePhoneNumber, normalizeCnpjNumber, normalizeCepNumber } from '../../Mask/mask'
const App = () => {
const {handleSubmit, watch,setValue } = useForm<FormValues>()
const onSubmit = handleSubmit((data) => console.log(data))
const phoneValue = watch("phone")
const cnpjValue = watch("cnpj")
const cepValue = watch("cep")
useEffect(() => {
setValue("phone", normalizePhoneNumber(phoneValue))
},[phoneValue])
useEffect(() => {
setValue("cnpj", normalizeCnpjNumber(cnpjValue))
},[cnpjValue])
useEffect(() => {
setValue("cep", normalizeCepNumber(cepValue))
},[cepValue])
return (
<form onSubmit={onSubmit}>
<input {...register("cnpj", {required: true})} />
<input {...register("phone", {required: true})} />
<input {...register("cep", {required: true})} />
</form>
)
}