Este artigo aborda as dificuldades comuns que os desenvolvedores enfrentam ao lidar com formulários — e como o React 19 finalmente introduz algumas ferramentas há muito esperadas que tornam o manuseamento de formulários mais limpo, mais declarativo e muito menos propenso a erros.
Nos últimos seis anos em desenvolvimento frontend — desde a construção de sistemas complexos de formulários até à integração de ferramentas de IA na SDG — escrevi, depurei e refatorei mais código de formulários do que gostaria de admitir.
E se alguma vez construiu ou manteve formulários em React, provavelmente partilha esse sentimento. São enganosamente simples... até não serem.
Neste artigo, vou guiá-lo pelas dificuldades comuns que os desenvolvedores enfrentam ao lidar com formulários — e como o React 19 finalmente introduz algumas ferramentas há muito esperadas que tornam o manuseamento de formulários mais limpo, mais declarativo e muito menos propenso a erros. ✨
🔍 Vamos começar com os pontos problemáticos que cada desenvolvedor React já enfrentou pelo menos uma vez.
Gerir o estado do formulário em React geralmente começa assim:
const [name, setName] = useState(''); const [surname, setSurname] = useState(''); const [error, setError] = useState(null); function handleSubmit(event) { event.preventDefault(); }
✅ É simples — e perfeitamente adequado para formulários pequenos.
Mas assim que escala, acaba por se afogar em hooks de estado repetitivos, resets manuais e chamadas intermináveis de event.preventDefault().
Cada tecla pressionada desencadeia uma nova renderização, e gerir erros ou estados pendentes requer ainda mais variáveis de estado. É funcional, mas longe de ser elegante.
Quando o seu formulário não é apenas um componente, mas uma hierarquia de componentes aninhados, acaba por passar props através de cada nível:
<Form> <Field error={error} value={name} onChange={setName}> <Input /> </Field> </Form>
Estado, erros, flags de carregamento — todos perfurados através de múltiplas camadas. 📉 \n Isto não só aumenta o código, mas torna a manutenção e refatoração dolorosas. 😓
Já tentou implementar atualizações otimistas manualmente?
É quando mostra uma alteração de "sucesso" na UI imediatamente após uma ação do utilizador — antes do servidor realmente a confirmar.
Parece fácil, mas gerir a lógica de reversão quando um pedido falha pode ser uma verdadeira dor de cabeça. 🤕
Onde armazena o estado otimista temporário? Como o funde e depois reverte? 🔄
O React 19 introduz algo muito mais limpo para isto.
Uma das adições mais empolgantes no React 19 é o hook ==*useActionState *==.
Simplifica a lógica do formulário combinando submissão assíncrona, gestão de estado e indicação de carregamento — tudo num só lugar. 🎯
const [state, actionFunction, isPending] = useActionState(fn, initialState);
Eis o que está a acontecer:
==fn== — a sua função assíncrona que lida com a submissão do formulário
==initialState== — o valor inicial do estado do seu formulário
==isPending== — uma flag incorporada que mostra se uma submissão está em progresso
\
A função assíncrona passada para ==useActionState== recebe automaticamente dois argumentos:
const action = async (previousState, formData) => { const message = formData.get('message'); try { await sendMessage(message); return { success: true, error: null }; } catch (error) { return { success: false, error }; } };
Depois liga-a ao seu formulário assim:
const [state, actionFunction, isPending] = useActionState(action, { success: false, error: null, }); return <form action={actionFunction}> ... </form>;
\n Agora, quando o formulário é submetido, o React automaticamente:
Não mais ==useState, preventDefault,== ou lógica de reset manual — o React cuida de tudo isso. ⚙️
Se decidir acionar a ação do formulário manualmente (por exemplo, fora da prop action do formulário), envolva-a com ==startTransition==:
const handleSubmit = async (formData) => { await doSomething(); startTransition(() => { actionFunction(formData); }); };
Caso contrário, o React irá avisá-lo que uma atualização assíncrona ocorreu fora de uma transição, e ==isPending== não será atualizado corretamente.
A lógica do formulário volta a ser declarativa — basta descrever a ação, não a cablagem.
Outro novo hook poderoso — ==useFormStatus== — resolve o problema de props drilling nas árvores de formulários.
import { useFormStatus } from 'react-dom'; const { pending, data, method, action } = useFormStatus();
Pode chamar este hook dentro de qualquer componente filho de um formulário, e ele conectar-se-á automaticamente ao estado do formulário pai.
function SubmitButton() { const { pending, data } = useFormStatus(); const message = data ? data.get('message') : ''; return ( <button type="submit" disabled={pending}> {pending ? `Sending ${message}...` : 'Send'} </button> ); } function MessageForm() { return ( <form action={submitMessage}> <SubmitButton /> </form> ); }
:::info Note que ==SubmitButton== pode aceder aos dados do formulário e ao estado pendente — sem que nenhum prop seja passado.
:::
🧩 Elimina props drilling nas árvores de formulários \n ⚡ Torna possíveis decisões contextuais dentro de componentes filhos \n 💡 Mantém os componentes desacoplados e mais limpos
Finalmente, vamos falar sobre uma das minhas adições favoritas — ==useOptimistic==.
Traz suporte incorporado para atualizações otimistas da UI, fazendo com que as interações do utilizador pareçam instantâneas e suaves.
Imagine clicar em "Adicionar aos favoritos". Quer mostrar a atualização imediatamente — antes da resposta do servidor.
Tradicionalmente, teria que fazer malabarismos entre estado local, lógica de reversão e pedidos assíncronos.
Com ==useOptimistic==, torna-se declarativo e mínimo:
const [optimisticMessages, addOptimisticMessage] = useOptimistic( messages, (state, newMessage) => [newMessage, ...state] ); const formAction = async (formData) => { addOptimisticMessage(formData.get('message')); try { await sendMessage(formData); } catch { console.error('Failed to send message'); } };
Se o pedido ao servidor falhar, o React automaticamente reverte para o estado anterior.
Se for bem-sucedido — a alteração otimista permanece.
A função de atualização que passa para useOptimistic deve ser pura:
❌ Errado:
(prev, newTodo) => { prev.push(newTodo); return prev; }
✅ Correto:
(prev, newTodo) => [...prev, newTodo];
:::tip Retorne sempre um objeto ou array de estado novo!
:::
Se acionar atualizações otimistas fora da action de um formulário, envolva-as em startTransition:
startTransition(() => { addOptimisticMessage(formData.get('message')); sendMessage(formData); });
Caso contrário, o React irá avisá-lo que uma atualização otimista aconteceu fora de uma transição. 💡
É o tipo de melhoria de UX que os utilizadores sentem — mesmo que não saibam por que a sua aplicação de repente parece tão rápida.
O React 19 simplifica significativamente o manuseamento de formulários — e pela primeira vez, não se trata de nova sintaxe, mas de melhorias reais na experiência do desenvolvedor.
🚀 Aqui está um resumo rápido do que usar e quando:
| Objetivo | Ferramenta React 19 | |----|----| | Aceder ao resultado da submissão do formulário | ==useActionState== | | Acompanhar submissão pendente



Taylor Swift alcançou em 2025 um patrimônio estimado em US$ 1,5 bilhão Getty Images Quando dois nomes que dominam áreas diferentes entram na mesma comparaç