Já ouviu falar no Yup?

Com o avanço da tecnologia e dos navegadores, percebemos que os fluxos que envolvem formulários tendem a ficar cada vez mais flexíveis para a pessoa usuária final. Com isso, temos um ponto chave, que são as validações de formulários. Podemos ter vários tipos de validações: uma para verificar obrigatoriedade, outra checando se o valor é um e-mail correto, entre muitos outros casos.

Na programação, devemos sempre pensar no conceito de DRY (Don’t repeat yourself), ou seja, não repetir o código. Dessa forma, quando trabalhamos com diversos formulários, podemos perceber que a validação dos navegadores é muito limitada e temos que criar as nossas próprias lógicas de validações. Sem tempo para pensar na melhor forma de escrever os códigos para isso, podemos acabar violando a regra do clean code.

Com Yup, temos uma maneira simples de validar qualquer tipo de campo, e com a ajuda do Formik conseguimos componentes reutilizáveis e flexíveis que nos permitem criar estilos personalizados. Nesse post mostraremos um pouco de cada ferramenta e também alguns exemplos práticos, continue com a gente!

O que é o Yup? e como funciona? 

É um construtor de esquemas para validação de campos e transformação de valores no JavaScript. Simplificando, a partir do Yup temos o conceito de schema,que nada mais é que o formato que os seus campos devem seguir, ou seja, se tivermos um objeto, que dentro temos três campos que devem ser textos, a partir do Yup definimos um schema para isso. Os esquemas (schemas) são muito flexíveis e permitem modelar complexas validações, correlacionadas ou não e até mesmo transformação de valores.

Imaginemos que esses são os valores de um formulário:

  • nome: texto <obrigatório>;
  • idade: numérico <obrigatório>;
  • e-mail: texto <obrigatório> <email>;
  • website: texto <url>.

Com essas informações, podemos criar um schema no Yup para validar esses campos:

let schema = yup.object().shape({
  nome: yup.string().required(),
  email: yup.string().email().required(),
  idade: yup.number().required().positive().integer(),
  website: yup.string().url()
});

Aqui temos a criação do schema para validar os campos que foram passados. Sendo assim, com poucas linhas e de forma muito intuitiva conseguimos criar um esquema para validação dos nossos dados.

A forma que o Yup foi escrito é muito inspirada no Joi, a única diferença é que o Yup é focado principalmente para o desenvolvimento front-end. Na biblioteca, temos a separação de dois fluxos:

  • cast: que é um método que ajuda na transformação e desserialização de valores;
  • isValid: que verifica se a entrada do valor está modelada de maneira correta. Com isso, podemos separar esses dois passos ou até mesmo juntá-los.

Por que usar Yup em seu projeto React? Entenda a importância! 

A validação de formulários é algo bem difícil e muitas vezes exaustivo de se fazer manualmente. Pense que teremos que criar todo tipo de regra, como verificar se o campo está vazio, se o e-mail está correto, se contém o tamanho mínimo de caracteres, entre muitos outros casos. 

Com isso, percebemos que a validação se torna muito repetitiva e o código cada vez mais sujo, e, no fim, descobrirmos que teria sido mais simples utilizar o Yup na nossa aplicação. Com ele, poderíamos simplificar a forma de validar os campos e parar de repetir tanto código. Teríamos também um suporte incrível à internacionalização das mensagens de erros.

Instalação e importação do Yup

Instalando o Yup

Para instalar o Yup apenas rode um desses comandos:

npm install yup // npm i yup

Ou:

yarn add yup

Com isso, podemos seguir para a próxima etapa.

Importando o Yup em seu projeto

Para a importação do pacote, devemos utilizar o require quando estamos usando NodeJs ou então, o import se estamos utilizando o ambiente do navegador.

const yup = require("yup");

Ou:

import * as yup from "yup";

O que é Formik?

O Formik é uma biblioteca para auxiliar o desenvolvimento de formulários, isso é, simplificar a forma de utilização dos campos de texto, numéricos, checkbox, entre muitos outros. Nele temos a possibilidade de criar em poucas linhas formulários robustos que podem ou não conter regras de validação.

Você pode estar se perguntando o porquê do Formik ser citado nesse post. A resposta é bem simples: o criador dessa ferramenta adicionou um exclusivo suporte à biblioteca do Yup e, sendo assim, conseguimos utilizar o melhor dos dois mundos e fazer o desenvolvimento de telas com diversos formulários de maneira bem prática.

Exemplos de uso do Yup

Antes de mexer com o Yup, vamos criar o nosso projeto. Para isso, você vai precisar baixar o NodeJs na sua máquina. Além disso, eu recomendo a utilização do Yarn para a instalação dos pacotes.

Vamos começar criando um novo diretório. No meu caso irei criar uma pasta chamada teste-yup:

mkdir teste-yup

Logo em seguida, entre na pasta que criamos e inicie um novo projeto:

cd teste-yup
npm init -y

Obs: O -y é para confirmar todas as questões que são feitas pelo Npm.

Continuando, na pasta do projeto, vamos primeiro criar um novo arquivo JavaScript:

touch index.js

Após isso, vamos no package.json e adicionaremos um novo comando para facilitar a execução do arquivo.

No package.json:

{
  ...
  "scripts": {
    "start": "node index.js"
  },
  ...
}

Criando a base de dados e o schema de validação

Iremos agora importar o Yup nesse arquivo e a base de dados que iremos validar:

const yup = require("yup");
 
const valores = {
  nome: "Fulano",
  email: "[email protected]",
  idade: -19,
  website: "https://www.site.com"
}

Criamos um novo objeto no qual temos um nome, um email e um campo de idade. Para validar esses valores, devemos criar um schema de validação:

let schema = yup.object().shape({
  nome: yup.string().required(),
  email: yup.string().email().required(),
  idade: yup.number().required().positive().integer(),
  website: yup.string().url()
});

Na declaração da variável schema temos a utilização da biblioteca do Yup para definir um objeto por meio da função object() e logo em seguida escrevemos qual é o formato de objeto. Dentro disso temos que:

  • o nome é um texto obrigatório;
  • o email tem que ser válido e também obrigatório;
  • a idade tem que ser um número, obrigatório, positivo e inteiro.

Validando dados através do schema

Para validar os nossos valores, temos que utilizar alguns outros métodos do Yup:

schema
  .isValid(valores)
  .then((valid) => {
    console.log("Valor válido:", valid);
  });

Aqui iniciamos a validação de um valor por meio do método isValid(). Passamos então o objeto criado anteriormente com o valor da idade incorreta. Por fim, depois do método then(), mostramos o resultado da validação em uma string, para facilitar a visualização.

Rodando um dos comandos a seguir temos o resultado da validação:

npm run start
yarn start
Resultado da validação

Podemos agora arrumar os valores que a gente passou:

const valores = {
  nome: "Fulano",
  email: "[email protected]",
  idade: 19,
  website: "https://www.site.com"
}

Se rodarmos novamente, perceberemos um novo tipo de resultado:

Novo resultado gerado no código com Yup

Dessa forma, conseguimos entender a força que o Yup pode nos proporcionar. 

Validações de formulários usando Formik e Yup

Vamos começar criando um novo projeto do React a partir da ferramenta create-react-app:

npx create-react-app teste-formik-yup

Após a criação do projeto, vamos entrar na pasta e instalar o Formik e o Yup:

cd teste-formik-yup
yarn add formik yup

Finalizada a instalação das dependências, iremos deletar todo o conteúdo da pasta src e criaremos um arquivo index.js e um arquivo de estilos styles.css:

cd src/
rm -f *
touch index.js
touch styles.css
cd ../

Para facilitar, copie os códigos a seguir nos arquivos criados:

// index.js
import React from "react";
import ReactDOM from "react-dom";
import { useFormik } from "formik";
import "./styles.css";
import * as yup from "yup";
 
const ExemploTrybe = () => {
  const formik = useFormik({
    initialValues: {
      nome: "",
      email: "",
      idade: "",
    },
    validationSchema: yup.object({
      nome: yup.string().required("O campo é obrigatório."),
      email: yup
        .string()
        .email("E-mail inválido.")
        .required("O campo é obrigatório."),
      idade: yup
        .number()
        .required("O campo é obrigatório.")
        .positive("O campo deve ser positivo.")
        .integer("O campo deve ser um número inteiro."),
    }),
    onSubmit: (values) => {
      alert(JSON.stringify(values, null, 2));
    },
  });
  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="nome">Nome</label>
      <input
        id="nome"
        name="nome"
        type="text"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.nome}
      />
      {formik.touched.nome && formik.errors.nome ? (
        <div>{formik.errors.nome}</div>
      ) : null}
      <label htmlFor="email">E-mail</label>
      <input
        id="email"
        name="email"
        type="email"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.email}
      />
      {formik.touched.email && formik.errors.email ? (
        <div>{formik.errors.email}</div>
      ) : null}
      <label htmlFor="idade">Idade</label>
      <input
        id="idade"
        name="idade"
        type="number"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.idade}
      />
      {formik.touched.idade && formik.errors.idade ? (
        <div>{formik.errors.idade}</div>
      ) : null}
      <button type="submit">Enviar</button>
    </form>
  );
};
 
function App() {
  return <ExemploTrybe />;
}
 
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

E para estilizar o nosso template

/* styles.css */
* {
    box-sizing: border-box;
}
 
body {
    background-color: #cbd5e0;
}
 
label {
    margin-top: 1rem;
    font-weight: bold;
    display: flex;
}
 
input {
    width: 400px;
    padding: 0.65rem 0.5rem;
    font-size: 1rem;
    border: 2px solid #edf2f7;
    background-color: #f7fafc;
    color: #2d3748;
    border-radius: 10px;
}
 
input:focus {
    outline: none;
}
 
button {
    padding: 0.5rem 1.25rem;
    font-size: 1rem;
    border-radius: 10px;
    background-color: #4a5568;
    border: 2px solid #4a5568;
    color: white;
    font-weight: bold;
    margin-bottom: 1rem;
    cursor: pointer;
    display: flex;
    margin-top: 1rem;
}

Vamos agora analisar cada parte do nosso código fonte:

...
const formik = useFormik({
    initialValues: {
      nome: "",
      email: "",
      idade: "",
    },
    validationSchema: yup.object({
      nome: yup.string().required("O campo é obrigatório."),
      email: yup
        .string()
        .email("E-mail inválido.")
        .required("O campo é obrigatório."),
      idade: yup
        .number()
        .required("O campo é obrigatório.")
        .positive("O campo deve ser positivo.")
        .integer("O campo deve ser um número inteiro."),
    }),
    onSubmit: (values) => {
      alert(JSON.stringify(values, null, 2));
    },
  });
...

Por início, temos a criação de uma variável do Formik, na qual por meio do hook useFormik, iniciamos os valores iniciais, o schema de validação do Yup e a função do evento de submit do formulário. No esquema usamos as mesmas regras mostradas anteriormente com a diferença das mensagens traduzidas.

Continuando:

...      
     <label htmlFor="nome">Nome</label>
     <input
        id="nome"
        name="nome"
        type="text"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.nome}
      />
      {formik.touched.nome && formik.errors.nome ? (
        <div>{formik.errors.nome}</div>
      ) : null}
...

Aqui temos uma label com um campo de texto que contém propriedades do Formik nas props onChange, onBlur e value, sendo que o onChange é chamado quando ocorre uma alteração no campo, o onBlur quando o campo é desfocado e o value é o valor do campo em si. Tudo isso é necessário para que a biblioteca consiga validar corretamente o campo.

Na linha de baixo temos uma checagem de erros que o Formik tenha percebido, se houver, é renderizado uma div com o erro, se não, nada ocorre.

Como podemos perceber, a repetição de toda essa lógica de props e a verificação de erros ocorre em todos os campos de textos do código. Isso foi feito para facilitar o entendimento, porém, é de suma importância trabalhar de forma genérica na programação.

Depois de tudo isso você pode checar o resultado desse pequeno projeto. Apenas rode o comando inicializador no seu terminal:

npm start

Ou:

yarn start
Formulário resultado do código com Yup

Lançar um objeto

No Yup também temos a possibilidade de utilizar a função cast () para converter um objeto para os valores corretos do schema, isso é, se no objeto de entrada tiver um número que está como texto, o lançamento do Yup vai convertê-lo para um número. Também seria possível converter uma string para um valor dia/mês/ano no object Date.

Nesse ponto, percebemos que essa biblioteca consegue agregar muito mais que apenas uma validação. Conseguimos com ela também corrigir os nossos valores do schema e ajustar o nosso fluxo de dados.

Métodos úteis

Listaremos a seguir algumas funções que podem auxiliar você nos seus projetos que utilizam o Yup:

  • se for interessante para você, existe o método concat () para juntar dois ou mais schemas de validação, lembrando que apenas esquemas do mesmo tipo podem ser concatenados;
  • podemos cancelar a validação no primeiro erro encontrado. Por padrão, o Yup vai validar todos os campos até retornar uma resposta. No entanto, se você passar a configuração abortEarly, ele vai interromper a execução no primeiro erro encontrado. O código pode ser escrito como:
wait checkoutAddressSchema.validate(addressFormData, { abortEarly: false })
  • temos outras funções de utilidade numérica, tais como o round (), que serve para arredondar um número, o morethan (), que verifica se o valor é apenas maior que o outro e o lessthan (), que ao contrário do anterior, verificar se o valor é menor que um outro;
  • também existe a possibilidade de usar regex no Yup, permitindo assim uma enorme personalização de regras.

Nesse post mostramos a dificuldade que é criar validações flexíveis e escaláveis para a pessoa usuária final, entendemos também o funcionamento do Yup e como ele pode ser útil para organizar o nosso fluxo de dados com a sua lógica de schemas. Por fim, com o Formik, aprendemos a fazer a integração com o Yup e a mostrar erros personalizados na tela.

Conseguimos com poucas linhas criar validações completas e totalmente voláteis para o nosso cenário, utilizando essas bibliotecas e um pouco de criatividade, conseguimos criar uma solução leve e rápida para os nossos problemas com formulário. Espero que as dúvidas sobre validações no front-end tenham sido sanadas!

O que achou de nosso texto? Leia agora sobre React: o que é e como funciona essa biblioteca Javascript?

Deixe um comentário
Você também pode gostar