qual é a diferença de fazer o tratamento do envio do form usando a propriedade onSubmit ou a propriedade action ?
qual é a diferença de fazer o tratamento do envio do form usando a propriedade onSubmit ou a propriedade action ?
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.