ReactJS: Formulários
Tags: forms, react, yup
Published: 2020-08-13 01:07:58


Você precisa de uma biblioteca de formulários para trabalhar com react?

Minha relação com o react quando se trata de formulários era de amor e ódio, e muito disso vinha do fato de que o react não opina muito sobre como as coisas devem ser feitas, outro ponto é que no Angular (eu usava Angular) a forma de criar formulários é incrível, e não encontrei nada parecido para react, formulários reativos é fantástico.

>[Get in touch with me on Twitter](https://twitter.com/juciano_barbosa)

Bem as coisas melhoraram com a API de hooks do react, criar formulários se tornou bem mais simples e me faz pensar se realmente é necessária uma biblioteca de formulários. No decorrer dessa serie vou mostrar duas formas de criar formulários sem precisar de uma biblioteca, e no final decida se é ou não necessário uma biblioteca, porem independente de qual seja sua opinião no final dessa postagem espero que os exemplos mostrados aqui sirva para algo.

Este é o primeiro exemplo de formulários sem bibliotecas nesta postagem vou explorar uma maneira eficiente de criar componentes de formulários avançados sem precisar de bibliotecas. **E no final um bônus…**

## Requisitos básicos

Para pôr em prática os passos dessa postagem é necessário cumprir alguns requisitos:

* Conhecimento básico de Javascript.

* Conhecimento básico de react.

* NodeJs instalado no ambiente.

Nesta postagem irei usar o **yarn** , sinta se a vontade para usar **npm**, e apesar de em produção escrever em typescript vou postar em javascript para abranger mais pessoas.

## Primeiros passos

Para iniciar precisamos criar uma aplicação reactjs e para isso rodamos o comando:

    npx create-react-app react-form
    cd react-form
    yarn
    yarn start

Estamos criando uma aplicação, navegando até o diretório dela, instalando as dependências e iniciando a aplicação.

Bibliotecas de formulários podem ser opcionais, bibliotecas de validação de formulários na minha opinião não, e para essa tarefa uso o **Yup**, e melhorar a aparência vou utilizar o **Bootstrap**.

    yarn add bootstrap
    yarn add yup

O create-react-app cria alguns arquivos que não serão necessários para o proposito deste tutorial, por isso exclui alguns arquivos, veja como ficou os arquivos restantes:

![](https://cdn-images-1.medium.com/max/2000/1*P8fTwj1DIETEFG6BlOf5iA.png)

**index.css**

![](https://cdn-images-1.medium.com/max/3160/1*XF0E8Jqbhk5S3-AwosHyQA.png)

**App.js**

![](https://cdn-images-1.medium.com/max/2000/1*LHCWhbgjx6EisAuZsIAofg.png)

**index.js**

![](https://cdn-images-1.medium.com/max/2308/1*JgEUTHBY3E8cNUcKPqPIUw.png)

## **Formulário com input controlado**

Formulário com componentes controlados são o exemplo mais comum inclusive em bibliotecas. Nessa abordagem a cada mudança no valor do input uma função é chamada para atualizar o valor que é salvo no estado do componente:

![](https://cdn-images-1.medium.com/max/2664/1*2Yzn_7zzUM7IbQRqwcQ1bQ.png)

Vou criar uma pasta para cada componente, sendo assim os arquivos devem ter o node index.jsx ou index.js.

Para criar um formulário seguindo essa abordagem vou primeiro criar um componente em Components/FormControlled/Input, este componente vai ser responsável por exibir uma label, um input e em caso de erro um spam, contendo a mensagem de erro. Notem que esse componente também esta validando se o input já foi tocado, isso é útil para exibir eventuais erros.

![](https://cdn-images-1.medium.com/max/3136/1*xIOoQjJadAwRnhQaaIjsYA.png)

O anfitrião desse componente esta em Components/FormControlled, bem nesse componente é onde de fato vou criar o formulário, inicio criando o estado inicial do formulário e setamos esse valor inicial em um hook useState, depois criamos uma função para facilitar a mudanças que ocorrem em cada input.

Finalmente no template tenho os **inputs** e em cada input declaramos um nome, a função **setInput **que é disparada a cada mudança e uma label.

![](https://cdn-images-1.medium.com/max/3136/1*jIEUE4UyXPW1Vt4lYsfMpg.png)

Ps* faltou adicionar as propriedades values dos Inputs no exemplo, cada propriedade recebe seu valor correspondente do objeto form.

Para ter o aplicativo funcionando preciso voltar para o App.jsx e fazer algumas alterações.

![](https://cdn-images-1.medium.com/max/2016/1*Nj9Y1isTkEFsWWdkNWWbmQ.png)

Agora o aplicativo de formulários já esta funcionando, rode o comando:

    yarn start

## Adicionando validações nos campos

Como mencionado no início vou usar o Yup para criar as validações, creio que é a melhor opção para validação, pois esse pacote traz uma grande quantidade de recursos que se fossem escritos na mão levaria um certo tempo, neste cenário estou criando um objeto com a mesma estrutura do objeto gerado no formulário e estou atribuindo a cada propriedade certas regras que devem ser cumpridas pelos valores digitados no formulário, nesse momento também aproveito para cadastrar as mensagens que serão exibidas.

![](https://cdn-images-1.medium.com/max/2136/1*9RaDiJS6yQ_Kd3zwyRFafA.png)

Vou voltar para o **Components/FormControlled** e adicionar esse recurso ao formulário.

### Analisando as mudanças:

1 — Adicionado um novo estado para erros — linha 16.

2 — Adicionada função **validate**, esta função deve tentar passar os valores do form pelo crivo das validações que foram escritas na etapa anterior, se ela obtiver sucesso eu seto o estado de erros com um objeto vazio, mas se houver um erro de validação o fluxo entra no bloco **catch,** esse bloco não pega apenas erros oriundos da **promise** de validação por isso faço uma validação se o erro é uma instância de **ValidationError** caso seja afirmativo atualizo o estado de errors com os valores recebidos . É importante notar que o processo de validação é assíncrono por isso uso um **async await **nessa função — linha 16 a 31.

3 — hook **useEffect** recebendo **form** como dependência e executando a validação a cada mudança em **form **— linha 37.

4 — Estou utilizando a propriedade **error** no componente de **input** e passando o objeto; **erros.[“nome do input”]** como valor — diversas linas no template.

![](https://cdn-images-1.medium.com/max/3080/1*je7QIcRmXAjatdVyEUGVeA.png)

Rode novamente o aplicativo e veja que agora o formulário esta funcionando perfeitamente e com validação.

![](https://cdn-images-1.medium.com/max/2000/1*TGVW5G3z762WRaeqteXEZw.png)

## Bônus

Acredito que a função validade e o hook useEffect poderiam ser abstraídos em um hook personalizado para organizar melhor o código e deixar o componente mais enxuto, então vou fazer essas mudanças.
> Criar seus próprios Hooks permite que você extraia a lógica de um componente em funções reutilizáveis.

Mais em [https://pt-br.reactjs.org/docs/hooks-custom.html](https://pt-br.reactjs.org/docs/hooks-custom.html)

### Criando o hook useValidations

Primeiro crio na raiz do projeto o diretório hooks/useValidations, e dentro dele crio um arquivo index.js, dentro desse arquivo basicamente eu coloco a lógica de validação, isso é a função **validade**, o **useState** de erros e o **useEffect** que invoca a função **validade, **o hook já esta escrito no componente, estou apenas separando ele para um novo arquivo, veja:

![](https://cdn-images-1.medium.com/max/2424/1*xccubSfBLs7LwGh5F0Li0Q.png)

**E como fica o componente de formulário?**

Apenas removo o código que foi transportado para o hook, note que o código do componente ficou bem mais limpo, importar o hook passar os valores do formulário e o **schema** de validação é tudo que eu preciso fazer, e o hook já devolve os erros:

![](https://cdn-images-1.medium.com/max/3080/1*Yl41g9SAv22Yw66qWPe2Ig.png)

## Pontos Positivos dessa abordagem

* Simplicidade no código — é um código bem simples e de fácil manutenção.

* Fácil de aplicar em formulários de vários steps, o elemento **form **em torno dos inputs é opcional, não preciso dele para submeter o formulário.

* Validação a cada mudança, torna a experiência do usuário bem mais atraente.

## Pontos Negativos dessa abordagem

* Esse não é o melhor exemplo em termo desempenho.

* O componente é reescrito a cada mudança no seu estado, isso significa que a cada digito no teclado o componente é rescrito(obvio que isso não inviabiliza o uso dessa abordagem, mas pesa negativamente.)

**Veja o código completo no meu github** :[https://github.com/Jucian0/react-form-controlled](https://github.com/Jucian0/react-form-controlled)

**E funcionando no Codesandbox**

<iframe src="https://medium.com/media/9310d26f79b70e40d3e00a9342ad349f" frameborder=0></iframe>

Se você tem mais algum ponto positivo ou negativo dessa abordagem, ou se tem algum ponto de melhoria no código não deixe de escrever nos comentários.

Segunda parte: https://dev.to/jucian0/react-formularios-parte-2-3gid

### Uma Alternativa

Se você acredita que ainda precisa de uma biblioteca de formulários não deixem de conferir um projeto que estou desenvolvendo:

Github do projeto [https://github.com/Jucian0/react-data-forms](https://github.com/Jucian0/react-data-forms)

Docs: [https://www.react-data-forms.org/](https://www.useform.org/)