Como construir formulários usando React Hook Form e Yup com ChakraUI

trinity_

Ivan Trindade

Posted on December 22, 2022

Como construir formulários usando React Hook Form e Yup com ChakraUI

Em HTML, é o comportamento padrão dos formulários redirecionar para uma nova página sempre que são enviados. Portanto, para fornecer funcionalidade dinâmica, o React usa uma estratégia chamada componentes controlados.

Se você fez recentemente um curso de React, provavelmente não gostou desta parte, porque há muitos estados para gerenciar se você tiver vários inputs.

Primeiramente, você rastreia o estado do input usando a propriedade onChange que chama a função useState(). Os inputs são agrupados em torno de um elemento de formulário.

Quando o usuário envia o formulário, ele aciona a propriedade onClick ou onSubmit para definir as entradas para uma array contendo valores ou objetos, dependendo do número de inputs.

Em seguida, vem a validação, que verifica se o usuário inseriu alguma entrada. Caso contrário, retorne um erro, solicitando que o usuário insira uma entrada válida.

A lógica aqui é um monte de clichê. Você pode ficar entediado só de ouvir sobre o processo.

E se eu te disser que uma única biblioteca pode conseguir tudo isso?

1. O que é React-Hook-Form?

2. Como o React-Hook-Form afeta o desempenho

3. Como obter dados do usuário de um formulário

4. Como adicionar validação aos seus formulários com Yup

5. Como obter dados do usuário em um formulário que utiliza bibliotecas externas

O que é React-Hook-Form?

React Hook Form é uma biblioteca flexível que cuida de toda a sua validação, gerenciamento de estado e dados do usuário - e está tudo compactado em um tamanho de apenas 25,3kb (descompactado) e 9,1kb GZip (alterações com versões).

É simples e direto de usar, e você precisa escrever um código mínimo.

Imagem com o tamanho do React-Hook-Form

Uma das características que me impressiona, é o seu desempenho. Conforme mencionado em seu Site oficial, React-Hook-Form:

Minimiza o número de re-renderizações e montagem mais rápida, esforçando-se para fornecer a melhor experiência do usuário.

Como o React-Hook-Form afeta o desempenho

Se você estiver utilizando as versões anteriores da biblioteca, a documentação geralmente faz referência á propriedade ref para manipular o gerenciamento e a validação do estado.

<input type=password placeholder=Password ref={register} />
Enter fullscreen mode Exit fullscreen mode

Dessa forma, o React-Hook-Form adota um método de entrada descontrolada, em vez de alterar o estado todas as vezes. Ele isola o componente selecionado e evita a renderização dos componentes filhos.

Isso reduz significamente o número de novas renderizações e aumenta o desempenho geral da aplicação.

Como obter dados do usuário de um formulário

E aqui está o que estaremos construindo. É um formulário simples com validação.

Eu criei um Codesandbox para este tutorial específico, portanto, certifique-se de consultá-lo caso se perca.

Aqui está o que você precisa acompanhar:

Link da aplicação

Código fonte

Imagem do formulário

Primeiro, vamos instalar as dependências:

Com npm:

npm i react-hook-form @chakra-ui/react @emotion/react @emotion/styled @hookform/resolvers yup
Enter fullscreen mode Exit fullscreen mode

Com yarn:

yarn add react-hook-form @chakra-ui/react @emotion/react @emotion/styled @hookform/resolvers yup
Enter fullscreen mode Exit fullscreen mode

Primeiro vamos fazer as importações:

import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";

import { useForm } from "react-hook-form";
Enter fullscreen mode Exit fullscreen mode

Crie as tipagens dos dados que serão enviados nos inputs:

type Form = {
  name: string;
  lastName: string;
  sex: string;
};
Enter fullscreen mode Exit fullscreen mode

Desestruture as seguintes constantes do hook useForm e atribua o schema com as validações ao resolver do useForm:

const { register, formState, control, handleSubmit } = useForm();
Enter fullscreen mode Exit fullscreen mode

Desestruture as constantes errors e isSubmitting de formState:

const { errors, isSubmitting } = formState;
Enter fullscreen mode Exit fullscreen mode

Usaremos a constante errors para acessar a mensagem de erro retornada do schema de validações. Por último, usaremos o isSubmitting na propriedade isLoading do botão do Chakra, para aparecer um spinner de carregamento enquanto o formulário está sendo enviado.

Crie um formulário simples como este:

<Flex as="form" onSubmit={handleSubmit(handleSend)}>
  <FormControl isInvalid={!!errors}>
  <Stack>
    <Input
      type="text"
      name="name"
      placeholder="Nome"
      ref={yup.ref}
      {...register("name")}
    />

    {!!errors && 
    <FormErrorMessage>
        {errors?.name?.message}
    </FormErrorMessage>}

    <Input
      type="text"
      name="lastname"
      ref={yup.ref}
      placeholder="Sobrenome"
      {...register("lastname")}
    />

    {!!errors && (
      <FormErrorMessage>
          {errors?.lastname?.message}
      </FormErrorMessage>
    )}

    <Controller
      control={control}
      name="sex"
      rules={{ required: true }}
      render={({ field }) => (
        <Stack>
          <Text size="md" fontWeight={500}>
            Sexo
          </Text>

          <RadioGroup color="gray.400" {...field}>
            <Stack spacing={5} direction="row">
              <Radio
                colorScheme="blue"
                value="Masculino"
                isInvalid={errors.sex?.type === "required"}
              >
                Masculino
              </Radio>

              <Radio
                colorScheme="blue"
                value="Feminino"
                isInvalid={errors.sex?.type === "required"}
              >
                Feminino
              </Radio>
            </Stack>
          </RadioGroup>

          {!!errors && (
            <FormErrorMessage>
                 {errors?.sex?.message} 
            </FormErrorMessage>
          )}
        </Stack>
      )}
    />

    <Button type="submit" isLoading={isSubmitting}>
      Enviar
    </Button>
  </Stack>
  </FormControl>
</Flex>
Enter fullscreen mode Exit fullscreen mode

Usamos a função register para fazer com que o valor seja validado e enviado no formulário:

<Input type="text" name="name" {...register("name")} />
Enter fullscreen mode Exit fullscreen mode

Para enviar os dados, criamos a função handleSend. Para que ela funcione usando Typescript, você precisará usar a tipagem SubmitHandler do próprio React-Hook-Form, passando a tipagem dos dados do seu formulário:

const handleSend: SubmitHandler<Form> = async (values) => {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    console.log({ submited: values });
  };
Enter fullscreen mode Exit fullscreen mode

Então passamos a função handleSend como parâmetro da função handleSubmit do próprio React-Hook-Form, para que os dados sejam enviados:

<Flex as="form" onSubmit={handleSubmit(handleSend)}>
   {...}
</Flex>
Enter fullscreen mode Exit fullscreen mode

Como adicionar validação aos seus formulários com Yup

Fazer validações nunca foi tão simples com o Yup, você pode fazer validações simples e complexas de forma extremamente expressiva.

Crie o schema com as validações:

const createFormSchema = yup.object({
    name: yup.string().required("Você deve digitar seu nome"),
    lastname: yup.string().required("Você deve digitar seu sobrenome"),
    sex: yup.string().required("Insira o seu sexo")
  });
Enter fullscreen mode Exit fullscreen mode

Agora atribua o schema de validações no resolver do useForm:

const { register, formState, control, handleSubmit } = useForm({
    mode: "onChange",
    resolver: yupResolver(createFormSchema)
  });
Enter fullscreen mode Exit fullscreen mode

Usamos a constante errors para validar que caso exista alguma mensagem de validação, ela seja renderizada no componente FormErrorMessage do Chakra, veja o exemplo:

{!!errors && 
    <FormErrorMessage>
        {errors?.name?.message}
    </FormErrorMessage>}
Enter fullscreen mode Exit fullscreen mode

Como obter dados do usuário em um formulário que utiliza bibliotecas externas

Se você analisar o código acima, perceberá que usamos a função register para fazer com que o valor seja validado e enviado no formulário. Então por qual motivo não estamos utilizando-o para registrar e validar o valor dos Radios?

O React-Hook-Form foi construído para ser usado com um HTML tradicional, sem uma biblioteca externa como o ChakraUI ou qualquer outra biblioteca semelhante. Estamos usando inputs do tipo radio personalizados do Chakra, portanto o React-Hook-Form não conseguirá registrar o valor dessa forma.

Para solucionar este problema, o Chakra fornece o componente Controller, no qual podemos usá-lo para registrar e validar os valores de componentes que usamos de bibliotecas externas.

Obrigado por ler! ✨

É bom ver que você leu até aqui. Se você obteve algumas informações com este artigo, sinta-se à vontade para compartilhá-lo com sua comunidade e colegas de trabalho.

Eu falo sobre tecnologias da web e projetos de construção,
documentando ainda mais o processo de desenvolvimento para outros desenvolvedores fazerem referência. Se precisar de alguma orientação, não deixe de comentar aqui.

💖 💪 🙅 🚩
trinity_
Ivan Trindade

Posted on December 22, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related