Criando um formulário sem uso de bibliotecas para formulários - ReactJS

Existem diversas formas para validar um formulário utilizando react, seja utilizando bibliotecas como react-hook-form ou até mesmo sem utilizar nenhuma biblioteca. Vou mostrar uma…

Postado em: September 15, 2023 12:35 PMLeandro ViegasLeandro Viegas

Existem diversas formas para validar um formulário utilizando react, seja utilizando bibliotecas como react-hook-form ou até mesmo sem utilizar nenhuma biblioteca.

Vou mostrar agora uma forma prática para validar formulários sem utilizar uma biblioteca para formulários de maneira muito simples.

Tudo o que precisamos é guardar o valor de todos os nosso campos em um state(estado) para depois validar antes do formulário ser enviado.

Vamos começar pelos useState no qual iremos armazenar os valores dos nossos campos e erros:

Agora vamos fazer a validação dos campos.

const [inputsErrors, setInputsErrors] = useState<{
    username: string[];
    email: string[];
    password: string[];
}>({
    username: [],    
    email: [],
    password: []
});

const [form, setForm] = useState<{ username: string; email: string; password: string; }>();

Colocando o form no useEffect conseguimos fazer a validação do formulário toda vez que o usuário muda os valores dos campos.  

Utilizando if e else if podemos fazer a verificação dos campos e guardar as mensagens que serão exibidas na tela.

const validateEmail =(email)=> /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);

useEffect(() => {
    setInputsErrors({
        username: [],
        email: [],
        password: []
    });
// Username validation
if (!(form?.username?.length > 0))
        setInputsErrors((errors) => ({ ...errors, username: ["Nome de usuário é obrigatório."] }));
else if (!(form?.username?.length > 3))
        setInputsErrors((errors) => ({ ...errors, username: ["Nome de usuário precisa ter ao menos 3 caracteres."] }));

// Email validation
if (!(form?.email?.length > 0))
        setInputsErrors((errors) => ({ ...errors, email: ["Email é obrigatório."] }));    
    else if (!validateEmail(form?.email))
        setInputsErrors((errors) => ({ ...errors, email: ["Email invalido."] }));

// Username validation
if (!(form?.password?.length > 0))
        setInputsErrors((errors) => ({ ...errors, password: ["Senha é obrigatório."] }));
    else if (!(form?.password?.length > 8))
        setInputsErrors((errors) => ({ ...errors, password: ["Senha precisa ter ao menos 8 caracteres."] }));
}, [form]);

Em seguida vamos cria a função que será executada quando o formulário for enviado.

const [formSentError, setSentFormError] = useState(false);

const HandleFormSubmit = (evt: React.FormEvent<HTMLFormElement>) => {
    evt.preventDefault();
    if(Object.keys(inputsErrors).some((input) => inputsErrors[input]?.length > 0)) {
    setSentFormError(true);
    } else {
    // The form is valid
    }
};

A primeira parte do código será armazenado um valor booleano para caso o formulário seja enviado e algum dos campos esteja com os dados errados. Com essa informação poderemos estilizar para que o formulário demonstre estar errado por meio da cor vermelha.

Dentro da função temos o código para previnir que a página recarregue ao formulário ser enviado e também um if else que verifica se há alguma mensagem de erro para ser exibida e caso tenha definiremos o valor boleano para true, indicando que os campos foram preenchidos de maneira incorreta, caso contrário você poderá colocar o código para salvar os dados no banco de dados por meio de uma api.

Por ultimo vamos fazer a parte visual do formulário com os botões, campos e botão de envio funcional.

Vamos começar pelos estilos. Eu utilizei nesse projeto a biblioteca styled-components para estilizar o formulário, mas, você pode usar css, scss ou qualquer outra tecnologia de estilização.

const Form=styled.form`
    text-align: left;
    background: #fff;
    max-width: 400px;
    border-radius: 10px;
    position: relative;
    margin: 0 auto;
    top: 40px;
    box-shadow: 0 0 12px #00000055;
    &>div {
      padding: 30px40px;
    }
    & h1 {
      color: #333;
      padding-bottom: 25px;
    }
    & .form-inputs {
      display: flex;
      flex-direction: column;
      gap: 20px;
    }
`;

Para a estilização dos botões e campos eu utilizei a biblioteca @mui/material que possui muitas opções de estilização de componentes. Assim ficou o código.

return (
    <FormonSubmit={HandleFormSubmit}>
      <div>
        <h1>Cadastrar-se</h1>
        <divclassName="form-inputs">
          <TextField
            onChange={(evt)=> setForm({ ...form, username: evt.target.value })}
            error={formSentError && inputsErrors["username"]?.length > 0}
            helperText={inputsErrors["username"]}
            autoComplete="off"
            color="secondary"
            id="username"
            label="Nome de usuário"
            variant="standard"
          />
          <TextField
            color="secondary"
            onChange={(evt)=> setForm({ ...form, email: evt.target.value })}
            error={formSentError && inputsErrors["email"]?.length > 0}
            helperText={inputsErrors["email"]}
            autoComplete="off"
            id="email"
            label="Email"
            variant="standard"
          />
          <TextField
            color="secondary"
            onChange={(evt)=> setForm({ ...form, password: evt.target.value })}
            error={formSentError && inputsErrors["password"]?.length > 0}
            helperText={inputsErrors["password"]}
            id="password"
            autoComplete="off"
            label="Senha"
            type="password"
            variant="standard"
          />
        </div>
        <Button
          type="submit"
          color="secondary"
          sx={{marginTop:"30px"}}
          variant="outlined"
        >
          Registrar-se
        </Button>
      </div>
    </Form>
  );

Para ver todo o código em execução acesse o code sandbox do projeto: https://codesandbox.io/s/formulario-cadastro-de-usuario-pd50z8​​​​

Editado em September 15, 2023 12:35 PM

Comentários



Leandro Viegas Profile Picture

Leandro Viegas

Desenvolvedor Fullstack

Tópicos