Problema/Solução
30 problemas comuns do React 19 que os desenvolvedores enfrentam, cada um com uma correção concisa. Ordenados do mais comum primeiro.
Busque em todas as páginas da documentação
30 problemas comuns do React 19 que os desenvolvedores enfrentam, cada um com uma correção concisa. Ordenados do mais comum primeiro.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
forwardRef parece redundante após a atualizaçãoProblema: Você tem dezenas de componentes forwardRef que agora parecem código repetitivo.
Solução: Aceite ref como uma prop regular.
interface InputProps extends React.ComponentPropsWithoutRef<"input"> {
ref?: React.Ref<HTMLInputElement>;
}
export function Input({ ref, ...props }: InputProps) {
return <input ref={ref} {...props} />;
}useFormState quebradaProblema: useFormState de react-dom avisa ou falha.
Solução: Importe useActionState de react - mesma assinatura mais isPending.
import { useActionState } from "react";
const [state, action, isPending] = useActionState(submit, null);Problema: Código que funcionava no React 18 agora lança erros de hidratação.
Solução: Mova window, Date.now(), Math.random() para useEffect ou um filho exclusivo para cliente.
<title> e <meta>Problema: react-helmet + o hoisting nativo de metadados do React 19 produzem tags duplicadas.
Solução: Remova react-helmet. Renderize <title>/<meta> diretamente em qualquer lugar - o React 19 os hoisting.
Problema: Exceções lançadas dentro de Server Actions aparecem como Server Error sem stack em produção.
Solução: Retorne erros como valores, não exceções.
"use server";
export async function save(_: State, fd: FormData) {
const title = fd.get("title");
if (!title) return { error: "Título é obrigatório" };
return { ok: true };
}use(promise) causando suspense infinitoProblema: Componente suspende para sempre após adicionar use().
Solução: A promise deve ser estável entre renders - crie-a em um pai ou memoize.
const userPromise = useMemo(() => fetchUser(id), [id]);
const user = use(userPromise);Problema: Marcar um Client Component como async lança "async/await ainda não é suportado."
Solução: Componentes assíncronos são apenas para servidor. Busque no servidor, passe como prop ou use use() no cliente.
useOptimistic volta rapidamenteProblema: UI otimista reverte antes que o servidor responda.
Solução: Envolva a mutação em startTransition ou chame de um Server Action.
startTransition(async () => {
addOptimistic(item);
await saveItem(item);
});Problema: <MyContext.Provider value={...}> parece verboso.
Solução: Renderize o próprio contexto - o React 19 aceita <MyContext value={...}>.
Problema: Nenhum hook de desmontagem quando um ref DOM é desmontado.
Solução: Retorne uma função de limpeza da callback do ref.
<div ref={(node) => {
const ob = new ResizeObserver(() => {});
if (node) ob.observe(node);
return () => ob.disconnect();
}} />Problema: Campos do formulário mantêm seus valores após um Server Action bem-sucedido.
Solução: Redefina via form.reset() em um requestFormReset dentro da ação, ou use uma prop key não controlada.
<form key={submitCount} action={action}>...</form>useActionStateProblema: Passar undefined como estado inicial quebra o primeiro render.
Solução: Sempre passe um padrão explícito como null ou {}.
useFormStatus sempre retorna pending: falseProblema: useFormStatus() chamado no pai do <form> nunca atualiza.
Solução: Ele apenas lê o status de um <form> ancestral. Chame-o de um filho renderizado dentro do formulário.
Problema: Retornar Date, Map ou instâncias de classe quebra silenciosamente.
Solução: Retorne apenas objetos simples compatíveis com JSON.
<head>Problema: <title> renderiza tarde quando dentro de uma árvore suspensa.
Solução: Faça hoisting dos metadados acima do limite do Suspense - layouts são ideais.
forwardRef perdem inferência TSProblema: Converter um forwardRef genérico para a prop ref perde a inferência de tipo.
Solução: Mantenha forwardRef para esse componente, ou restrinja a restrição genérica.
useTransition não adia renders carosProblema: UI ainda trava mesmo após envolver em startTransition.
Solução: Certifique-se de que o trabalho caro leia do estado atualizado dentro da transição, não de um setState síncrono separado.
Problema: Importar uma lib apenas para navegador em um Componente de Servidor lança window is not defined.
Solução: Adicione "use client" no topo do arquivo, ou importe dinamicamente com next/dynamic + ssr: false.
cache() não dedupica entre requisiçõesProblema: cache() do React parece cachear por requisição, mas não entre elas.
Solução: É o design - cache() é memoização por requisição. Para entre requisições, use unstable_cache (Next.js) ou um cache externo.
use() em um condicional após hooks causa errosProblema: Chamar use() dentro de um if após outro hook quebra as regras de hooks.
Solução: use() pode ser condicional, mas ainda conta como uma chamada de hook - mantenha-o antes de qualquer retorno antecipado.
Problema: Server Action é executado duas vezes em desenvolvimento.
Solução: Essa é a invocação dupla intencional do Strict Mode. Torne as ações idempotentes ou desative o Strict Mode apenas como último recurso.
ref + biblioteca de terceiros esperando forwardRefProblema: Uma biblioteca envolve seu componente e espera semântica de forwardRef.
Solução: Mantenha forwardRef no limite da integração - a compatibilidade ainda funciona.
useDeferredValueProblema: No primeiro render você quer pular o valor antigo.
Solução: O React 19 aceita um segundo argumento: useDeferredValue(value, initialValue).
const deferred = useDeferredValue(query, "");Problema: Fallback pisca mesmo para transições rápidas.
Solução: Envolva a navegação em startTransition para que o React mostre conteúdo antigo em vez do fallback.
<link rel="stylesheet"> carregando fora de ordemProblema: Múltiplos componentes renderizam a mesma stylesheet e a ordem é instável.
Solução: Use a prop precedence - o React 19 deduplica e ordena-os.
<link rel="stylesheet" href="/a.css" precedence="default" />Problema: Você injeta <link rel="preload"> manualmente e ele executa tarde demais.
Solução: Use as APIs de recursos do React 19: preload, preinit, prefetchDNS de react-dom.
import { preload } from "react-dom";
preload("/hero.jpg", { as: "image" });Problema: Erro de Server Action contorna seu <ErrorBoundary>.
Solução: Error boundaries capturam erros de renderização, não rejeições de ação. Exponha erros via valor de retorno de useActionState em vez disso.
action={serverAction} de formulárioProblema: TS reclama ao passar uma função de servidor para action.
Solução: Certifique-se de que @types/react ≥ 19 e que a assinatura da ação corresponda a (formData: FormData) => void | Promise<void>.
"use server" vazando código do clienteProblema: Importar utilitários compartilhados em um arquivo "use server" agrupa código exclusivo para cliente no lado do servidor.
Solução: Mantenha arquivos "use server" focados em ações - extraia a lógica compartilhada para um arquivo neutro lib/ sem importações do React.
ReactDOM.render legadoProblema: Código de bootstrap antigo usando ReactDOM.render não compila mais.
Solução: Mude para createRoot (obrigatório desde o 18, imposto no 19).
import { createRoot } from "react-dom/client";
createRoot(document.getElementById("root")!).render(<App />);Revisado por Chris St. John·Última atualização: 16 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥