Como validar formulário no React usando Formik e Yup

Uma das tarefas mais complicadas no desenvolvimento web é quando precisamos criar um formulário, e precisamos criar uma dezena de validações para que o usuário não envie informações erradas, ou acabe tendo uma experiência ruim com a nossa aplicação, com uma aplicação React é mais simples do que uma aplicação web tradicional usando somente html e javascript entretanto ainda dá trabalho.

Nesse exato momento pode ser onde nosso código que está todo organizado e bem pensado começa a tomar rumos desconhecidos e se transformar em algo que até você que criou não vai querer mexer.

Mas e se eu te falar que fazer isso hoje em dia não e tão trabalhoso assim? Bom nesse tutorial pretendemos apresentar uma forma de fazer isso de um jeito prático e escalável, existem duas bibliotecas que podem facilitar muito nosso trabalho são elas Formik e Yup, essas duas bibliotecas usadas juntas podem facilitar muito nosso trabalho.

Bom para começar vamos criar um projeto novo do zero, nossa proposta é fazer um formulário simples que colete algumas informações básicas como nome, idade e email.

Escolhemos essas informações pois podemos apresentar um exemplo que abrange alguns tipos de validações diferentes, sem mais enrolação vamos para o código.

Criando o nosso projeto

Para criar um novo projeto React é necessário ter o NodeJs devidamente instalado e alguma gerenciador de dependências como o próprio npm ou o yarn, caso você não tenha esses pré requisitos pode clicar aqui que temos um tutorial passo a passo de como instalar e configurar o seu ambiente e deixá-lo pronto para o React.

Agora que temos o nosso setup devidamente configurado vamos começar a criar o projeto, primeiro abre uma instancia do terminal e execute o seguinte comando.

npx create-react-app my-app --template typescript
Terminal

O uso do typescript não é obrigatório, você pode optar por fazer sem ele se quiser o processo é o mesmo.

Aguarde toda a instalação e após o termino vamos abrir a pasta gerada em alguma IDE ou editor, no nosso caso vamos usar o Visual Studio Code.

VALIDANDO FORMULÁRIO COM REACT 01
Visual Studio Code com o projeto aberto na pasta raiz.

Para garantir que o projeto está funcionando corretamente, vamos executá-lo, com o terminal na raiz do projeto execute o comando “npm start“, que vai executar um script do seu package.json disponibilizado pelo react na criação do projeto.

npm start
Terminal

Por padrão nosso projeto deve executar na porta 3000 pois essa é a configuração padrão gerada pelo React, caso ele não abra automaticamente no seu browser, para acessá-lo você pode navegar até o endereço http://localhost:3000.

Como resultado vamos ter o projeto template do React funcionando.

VALIDANDO FORMULÁRIO COM REACT 02
Projeto executando na porta 3000

Para demonstrar a validação nós vamos criar um formulário que captura, o nome, idade e e-mail de uma pessoa, e como requisitos vamos ter:

  • Nome: Deve ser uma String não deve conter menos de 3 caracteres e não mais que 55.
  • Idade: Deve ser um número inteiro entre 18 e 65.
  • Email: Deve ser um e-mail válido contendo o “@”.

Agora vamos criar o componente que abriga o nosso formulário, para isso vamos criar uma pasta chamada components dentro da pasta src e Adicioná-lo lá:

const Form = () => {
    return (
        <form>
            <label>Nome</label>
            <input type="text" name="name" />

            <label>Idade</label>
            <input type="text" name="age" />

            <label>E-mail</label>
            <input type="text" name="email" />

            <button type="submit">Enviar</button>
        </form>
    )
}

export default Form
Form.tsx

Não é necessário estilização, mas para trabalhar com o nosso formulário com um visual um pouco melhor vamos adicionar algumas linhas no arquivo index.css.

body, html, #root {
  height: 100%;
}

.content {
  display: flex;
  width: 100%;
  height: 100%;
  justify-content: center;
  align-items: center;
  padding: 20px;
  background-color: #EEE;
}

.content form {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 400px;
  max-width: 400px;
  min-height: 400px;
  background-color: #FFF;
  padding: 40px;
  justify-content: center;
  border: 1px solid #666;
  border-radius: 10px;
  box-shadow: 2px 2px 2px 2px #CCC;
}

.content form label {
  margin-top: 20px;
}

.content form input {
  padding: 10px;
  border-radius: 5px;
  border: 1px solid #333;
}

.content form button {
  padding: 10px;
  font-size: 16px;
  font-weight: 700;
  background-color: #054F77;
  color: #FFF;
  border: 1px solid #054F77;
  border-radius: 10px;
  cursor: pointer;
  margin-top: 20px;
}

.content form > span {
  color: #FF0000;
}
index.css

Agora precisamos importar o nosso formulário no arquivo App.tsx, para que ele renderize nosso componente, adicionamos a div somente para fins de estilização.

import React from 'react';
import Form from './components/Form';

function App() {
  return (
    <div className="content">
      <Form />
    </div>
  );
}

export default App;
App.tsx

Testando o que foi implementado até agora vamos ver que temos um formulário funcional e quando clicamos no botão Enviar, ele recarrega a página é um comportamento padrão de formulário html.

Instalando o Formik e Yup no projeto

Quem vai fazer a maior parte do trabalho pesado, é duas bibliotecas muito utilizadas na comunidade React, o Formik e o Yup, e para que elas servem?

O Formik vai encapsula o nosso formulário permitindo gerenciar ele de uma forma mais prática e recuperar os valores de uma forma mais intuitiva.

Já o Yup vai servir para escrevermos as regras de validação do formulário.

Para adicionar essas duas bibliotecas basta executar o comando abaixo no terminal na raiz do projeto

npm install formik yup
Terminal

Usando o hook useFormik

Com as duas bibliotecas instaladas vamos começar a lidar com o envio do formulário.

Para isso vamos usar o hook que o formik nos fornece e criar uma instancia que vai saber lidar com os eventos do formulário.

O hook do Formik necessita de alguns parametros, que são:

  • initialValues: Aqui deve ser passado um objeto JSON com as propriedades equivalentes no formulário.
  • onSubmit: Aqui deve ser passado uma função que será executada quando o formulário for submetido.

E precisamos mapear cada input do nosso formulário passando dois parâmetros para ele o onChange vamos passar o handlerChange do formik e no campo value precisamos passar o valor correspondente de cada input que vai ficar na instancia do formik.values, assim como na propriedade onSubmit do form precisamos passar o handlerSubmit do formik segue o exemplo:

import { useFormik } from "formik"

const Form = () => {
    const formik = useFormik({
        initialValues: { name: '', age: '', email: '' },
        onSubmit: values => {
            console.log(values)
        }
    })

    return (
        <form onSubmit={formik.handleSubmit}>
            <label>Nome</label>
            <input type="text" name="name" onChange={formik.handleChange} value={formik.values.name}/>

            <label>Idade</label>
            <input type="text" name="age" onChange={formik.handleChange} value={formik.values.age}  />

            <label>E-mail</label>
            <input type="text" name="email" onChange={formik.handleChange} value={formik.values.email} />

            <button type="submit">Enviar</button>
        </form>
    )
}

export default Form
Form.tsx

Se você tentar submeter o formulário agora clicando no botão Enviar note que no console do seu browser será impresso um objeto JSON contendo as informações de cada input.

Com isso nosso formulário já está funcional entretanto não está validando absolutamente nada.

Criando o schema de validação do formulário usando o Yup

Para que o Formik saiba como validar cada input é necessário passarmos para ele um esquema de validação, vamos construir esse esquema com a biblioteca yup instalada anteriormente.

Para criar nosso schema de validação vamos criar uma pasta que vai abrigar todos os nossos schemas e adicioná-lo lá com o nome de form-schema.ts.

import * as Yup from 'yup'

export const schema = Yup.object().shape({
    name: Yup.string().min(3).max(55).required(),
    age: Yup.number().min(18).max(65).required(),
    email: Yup.string().trim()
        .matches(/^[a-z0-9.]+@[a-z0-9]+\\.[a-z]+\\.([a-z]+)?$/i).required()
})
schema.ts

Se você notar estamos usando um RegEx para validar o campo e-mail, isso nos permite possibilidades quase que ilimitadas.

Agora precisamos importar nosso schema de validação e adicioná-lo a instancia do Formik na chave validationSchema.

import { useFormik } from "formik"
import { schema } from '../schemas/form-schema'

const Form = () => {
    const formik = useFormik({
        initialValues: { name: '', age: '', email: '' },
        validationSchema: schema,
        onSubmit: values => {
            console.log(values)
        }
    })

    return (
        <form onSubmit={formik.handleSubmit}>
            <label>Nome</label>
            <input type="text" name="name" onChange={formik.handleChange} value={formik.values.name}/>

            <label>Idade</label>
            <input type="text" name="age" onChange={formik.handleChange} value={formik.values.age}  />

            <label>E-mail</label>
            <input type="text" name="email" onChange={formik.handleChange} value={formik.values.email} />

            <button type="submit">Enviar</button>
        </form>
    )
}

export default Form
Form.tsx

Se tentarmos submeter o formulário com informações inválidas note que o formulário não envia mais, não imprimindo no console as informações.

Entretanto ainda não temos nenhuma informação visual de qual input está com a informação errada e isso é um ponto bem importante para o usuário.

Vamos resolver isso adicionando em uma tag span o feedback da validação de cada input, segue o exemplo.

import { useFormik } from "formik"
import { schema } from '../schemas/form-schema'

const Form = () => {
    const formik = useFormik({
        initialValues: { name: '', age: '', email: '' },
        validationSchema: schema,
        onSubmit: values => {
            console.log(values)
        }
    })

    return (
        <form onSubmit={formik.handleSubmit}>
            <label>Nome</label>
            <input type="text" name="name" onChange={formik.handleChange} value={formik.values.name}/>
            <span>{formik.errors.name}</span>

            <label>Idade</label>
            <input type="text" name="age" onChange={formik.handleChange} value={formik.values.age}  />
            <span>{formik.errors.age}</span>

            <label>E-mail</label>
            <input type="text" name="email" onChange={formik.handleChange} value={formik.values.email} />
            <span>{formik.errors.email}</span>

            <button type="submit">Enviar</button>
        </form>
    )
}

export default Form
Form.tsx

Agora quando tentamos enviar o formulário com informações erradas é nos mostrado um texto abaixo de cada input com o erro, mas está pouco amigável para o usuário principalmente considerando um usuário brasileiro, então vamos adicionar umas frases de validação mais amigáveis.

import * as Yup from 'yup'

export const schema = Yup.object().shape({
    name: Yup.string().min(3, "Minimo de caracteres aceitável é 3")
        .max(55, "Máximo de caracteres aceitável é 55")
        .required("O campo Nome é obrigatório"),
    age: Yup.number()
        .min(18, "Idade mínima aceitável é de 18 anos")
        .max(65, "Idade máxima aceitável é de 65 anos")
        .required("O campo idade é obrigatório"),
    email: Yup.string().trim()
        .matches(/^[a-z0-9.]+@[a-z0-9]+\\.[a-z]+\\.([a-z]+)?$/i, "Email inválido")
        .required("O campo E-mail é obrigatório")
})
schema.ts

Agora pode fazer todos os testes que quiser nosso formulário está funcional e validado cada input de acordo com o nosso schema.

Links úteis

Mauricio Lima
Mauricio Lima

Bacharel em Ciência da Computação, profissional dedicado ao desenvolvimento de software e entusiasta da tecnologia.

Artigos: 65