1
resposta

[Dúvida] onSubmit ou action?

qual é a diferença de fazer o tratamento do envio do form usando a propriedade onSubmit ou a propriedade action ?

1 resposta

Boa pergunta, Yann! E a resposta passa por entender uma mudança importante que o React 19 trouxe.

O jeito clássico: onSubmit

O onSubmit é o que a gente sempre usou. Você coloca um handler no <form>, e quando o formulário é enviado, esse handler recebe um evento. A primeira coisa que você faz (quase no automático) é chamar event.preventDefault() pra impedir o navegador de recarregar a página. Depois, você pega os valores dos inputs — geralmente via useState controlando cada campo — e faz o que precisa: valida, monta o body, chama uma API.

const [nome, setNome] = useState("");

const handleSubmit = (e) => {
  e.preventDefault();
  // faz alguma coisa com o nome
};

<form onSubmit={handleSubmit}>
  <input value={nome} onChange={(e) => setNome(e.target.value)} />
  <button type="submit">Enviar</button>
</form>

Funciona? Funciona. Mas repara na quantidade de coisas que você precisa gerenciar manualmente: o estado de cada campo, o preventDefault, o estado de loading se quiser mostrar um spinner, o estado de erro... É bastante código "mecânico" que não tem nada a ver com a lógica do seu formulário em si.

O jeito novo: action

No React 19, o <form> ganhou a possibilidade de receber uma função no prop action. Isso muda muita coisa.

Quando você passa uma função pro action, o React assume o controle do envio do formulário. Ele automaticamente chama preventDefault() pra você, coleta os dados do formulário como um FormData nativo, e passa esse FormData como argumento da sua função. Quando a action termina com sucesso, ele ainda reseta os campos não controlados sozinho.

function salvar(formData) {
  const nome = formData.get("nome");
  // faz alguma coisa com o nome
}

<form action={salvar}>
  <input name="nome" />
  <button type="submit">Enviar</button>
</form>

Olha a diferença. Sem useState pra controlar os inputs, sem preventDefault, sem handler de onChange. O React cuida de tudo isso por baixo dos panos. Você só escreve a lógica que importa.

E tem mais: a função passada pro action pode ser assíncrona. Isso abre a porta pra usar hooks novos como o useActionState (que gerencia estado de sucesso/erro da action) e o useFormStatus (que te dá um pending pra saber se o form tá sendo enviado). São hooks que foram pensados pra trabalhar junto com esse modelo de actions.

import { useActionState } from "react";

async function salvarAction(estadoAnterior, formData) {
  const nome = formData.get("nome");
  // chama a API, por exemplo
  return { sucesso: true, mensagem: `${nome} salvo!` };
}

function MeuForm() {
  const [estado, formAction] = useActionState(salvarAction, null);

  return (
    <form action={formAction}>
      <input name="nome" />
      <button type="submit">Enviar</button>
      {estado?.mensagem && <p>{estado.mensagem}</p>}
    </form>
  );
}

O useActionState encapsula a action e te devolve o estado retornado por ela. Nada de useState pra erro, useState pra loading, useState pra resultado. Tudo vive num lugar só.

Qual usar? Depende do cenário.

O action brilha em formulários mais diretos — cadastro, busca, envio de dados — onde você quer escrever menos código e aproveitar o gerenciamento automático do React 19. É especialmente poderoso se você tá usando um framework como Next.js com Server Actions, porque a mesma função pode rodar no servidor.

O onSubmit continua sendo útil quando você precisa de mais controle sobre o processo de envio. Por exemplo, se você usa uma lib de validação como React Hook Form ou quer fazer lógica complexa antes do envio (tipo confirmar com o usuário, manipular dados de formas específicas, etc). E nada impede de usar os dois juntos — dá pra ter um action no form e um onSubmit que faz validação client-side antes.