Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA

Aula 5 de 6

Formulário controlado no React: entrada e validação

Controle campos com estado, valide a entrada no envio e mostre mensagens acessíveis sem recarregar a página nem perder os dados existentes.

48 minutos · leitura + prática · nível iniciante

Ao terminar esta aula, você vai conseguir

  • Conectar value e onChange ao estado
  • Tratar o envio no evento submit do formulário
  • Exibir validação próxima ao campo e mover o foco quando necessário
O componente App se divide nos componentes Header, Lista e Botão.

Num formulário controlado, o valor exibido pelo campo vem do estado React e cada edição solicita uma atualização desse estado. Isso cria uma fonte de verdade para entrada, validação e envio. O navegador ainda oferece o campo real; React coordena qual valor ele apresenta.

Pense num atendente que repete o pedido no painel enquanto você fala. O painel mostra exatamente o registro atual e pode apontar uma informação incompleta antes de enviar à cozinha. O limite: atualizar estado a cada mudança não substitui validação no servidor. O cliente pode ser alterado ou ignorado, então regras de segurança e integridade precisam existir novamente na API.

Conecte value e onChange

O par fundamental é direto:

jsx
function CampoTitulo() {
  const [titulo, setTitulo] = React.useState('');
  const controle = {
    value: titulo,
    onChange: (evento) => setTitulo(evento.target.value),
  };

  return (
    <label>
      Título
      <input {...controle} />
    </label>
  );
}

value recebe o snapshot do estado. Quando a pessoa digita, onChange lê o novo valor do elemento e chama o setter. React renderiza novamente e o campo recebe o estado atualizado. Se você fornecer value sem onChange, o campo fica efetivamente somente leitura.

Trate o envio no formulário

Use o evento submit do <form>, não apenas o clique do botão. Assim Enter no campo e recursos nativos continuam funcionando:

jsx
function enviar(evento) {
  evento.preventDefault();
  const limpo = titulo.trim();

  if (limpo.length < 3) {
    setErro('Digite pelo menos 3 caracteres.');
    return;
  }

  setTarefas((atuais) => [
    ...atuais,
    { id: crypto.randomUUID(), titulo: limpo, concluida: false },
  ]);
  setTitulo('');
  setErro('');
}

preventDefault evita a navegação padrão da página porque o componente vai processar o envio. trim remove espaços nas pontas antes da regra. A atualização funcional preserva tarefas que já estavam no array e acrescenta um objeto novo.

Validação precisa orientar a correção

“Inválido” diz pouco. Informe o critério: “Digite de 3 a 60 caracteres”. Associe a mensagem ao campo com aria-describedby e use role="alert" para uma falha que surge depois do envio. Uma borda vermelha pode complementar, mas não deve ser a única indicação.

jsx
<label htmlFor="titulo">Título</label>
const controle = {
  value: titulo,
  onChange: (evento) => setTitulo(evento.target.value),
  'aria-invalid': Boolean(erro),
  'aria-describedby': 'erro-titulo',
};

<input id="titulo" {...controle} />
<p id="erro-titulo" role="alert">{erro}</p>

Para formulários maiores, mover o foco ao primeiro campo inválido pode ajudar. Faça isso com cuidado para não deslocar a pessoa sem uma ação previsível, como o envio.

Estado temporário e estado definitivo

O texto digitado é estado temporário do formulário; a tarefa só entra na coleção depois de passar pela regra. Não adicione um item vazio para depois tentar consertá-lo. Após sucesso, limpe o campo e o erro. Em uma aplicação com API, também existe estado de envio, sucesso e falha de rede.

Outros controles seguem a mesma ideia com formatos próprios. Uma caixa de seleção lê evento.target.checked; um <select>evento.target.value. Para um formulário com vários campos, você pode guardar um objeto e copiar as demais propriedades ao atualizar uma delas. O princípio continua: o estado representa o valor atual e a regra de envio trabalha sobre um snapshot coerente.

Teste também espaços no começo e no fim. A interface pode preservar o que está sendo digitado, mas o valor definitivo usa a versão normalizada por trim.

Erro comum: validar um estado antigo

Setters não trocam o valor do snapshot atual imediatamente. Evite chamar setTitulo(...) e na linha seguinte esperar que titulo já contenha o novo valor. Valide a variável derivada do evento ou do valor atual, como limpo, e use esse mesmo valor para criar a tarefa.

No laboratório, envie primeiro espaços, depois dois títulos válidos. A lista precisa manter ambos e o campo deve limpar apenas após sucesso. Na missão, adicione limites mínimo e máximo e mostre quantos caracteres restam. Na próxima aula, reunimos componentes, filtro e formulário no projeto final.

Laboratório ao vivo

Cadastro controlado de tarefa

Envie vazio, depois cadastre duas tarefas. Confirme a mensagem de erro, a limpeza do campo após sucesso e a preservação da primeira tarefa.

Pronto para testar
Resultado

Pare e pense

O que torna um campo de formulário controlado no React?

Escolha uma resposta
Missão da aula

Faça sem copiar

Adicione validação de 3 a 60 caracteres e contador do limite. A missão passa quando entradas fora da faixa não entram na lista e o foco continua utilizável.

Fontes para consultar

Terminou a missão?

Marque apenas quando você conseguir explicar o conceito e concluir o desafio. O progresso fica salvo somente neste navegador.

Próxima: Projeto React: painel de tarefas completo →