Documentação / 4 de 5

CPF e CNPJ em formulários React com TypeScript

Use um campo controlado para guardar o texto digitado e valide ao sair do campo ou enviar o formulário. O exemplo abaixo usa as mesmas operações para CPF e CNPJ, aceita minúsculas no CNPJ e mantém o texto original quando há erro.

Instale a biblioteca

Em um projeto React existente:

npm install cpf

Crie um campo reutilizável

import { useId, useState, type FormEvent } from 'react'
import cpf, { cnpj } from 'cpf'

type Props = {
  kind: 'cpf' | 'cnpj'
  onValid: (normalized: string) => void
}

export function DocumentForm({ kind, onValid }: Props) {
  const id = useId()
  const [value, setValue] = useState('')
  const [error, setError] = useState('')
  const document = kind === 'cpf' ? cpf : cnpj

  function validate(): string | null {
    if (!value.trim()) {
      setError('Preencha o documento.')
      return null
    }
    try {
      const normalized = document.normalize(value)
      if (document.isValid(normalized)) {
        setError('')
        return normalized
      }
    } catch {
      // Caracteres incompatíveis ou entrada longa também são inválidos.
    }
    setError(`Confira o ${kind.toUpperCase()} informado.`)
    return null
  }

  function handleBlur() {
    const normalized = validate()
    if (normalized !== null) setValue(document.format(normalized))
  }

  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault()
    const normalized = validate()
    if (normalized !== null) onValid(normalized)
  }

  return (
    <form onSubmit={handleSubmit} noValidate>
      <label htmlFor={id}>{kind.toUpperCase()}</label>
      <input
        id={id}
        name={kind}
        type="text"
        inputMode={kind === 'cpf' ? 'numeric' : 'text'}
        autoCapitalize="characters"
        spellCheck={false}
        value={value}
        onChange={event => {
          setValue(event.target.value)
          setError('')
        }}
        onBlur={handleBlur}
        aria-invalid={Boolean(error)}
        aria-describedby={`${id}-error`}
      />
      <p id={`${id}-error`} aria-live="polite">{error}</p>
      <button type="submit">Continuar</button>
    </form>
  )
}

Use <DocumentForm kind="cnpj" onValid={handleDocument} /> e implemente handleDocument com o fluxo da sua aplicação. O callback recebe somente o valor normalizado depois de ele passar pela validação.

Por que formatar ao sair do campo?

O onChange copia o texto digitado sem transformá-lo. Isso mantém o comportamento de seleção e edição do campo controlado; a máscara só é aplicada no onBlur, depois de validar. A documentação de inputs do React explica a atualização síncrona do estado e os problemas de cursor ao transformar o valor durante a digitação.

Em um componente de servidor, coloque esse formulário em um componente cliente. Se o framework exigir uma diretiva como 'use client', ela deve vir antes dos imports. Valide novamente no servidor antes de persistir o documento.

Formatação não consulta cadastro

Um retorno válido confirma a estrutura e os verificadores. O aplicativo continua responsável por confirmar titularidade ou situação cadastral quando isso for necessário. Para mais detalhes, veja CPF, CNPJ alfanumérico e máscaras durante a digitação.

Voltar ao início · Relatar um problema