Um guia passo a passo para inspecionar arquivos de UI React e Next.js e decidir o que refatorar. Execute as etapas em ordem nos arquivos em escopo (uma rota, uma pasta de funcionalidade ou um diff de PR). As etapas anteriores remodelam a área de superfície; as etapas posteriores apertam o que resta. Pule uma etapa apenas se você já verificou que ela está limpa.
Abra todos os arquivos da funcionalidade ou rota ao mesmo tempo - app/<rota>/page.tsx, seus componentes filhos, seu actions.ts e quaisquer hooks colocados em conjunto.
Faça um pequeno PR por etapa que você executar. Não agrupe uma conversão de Server Component com uma passagem de memoização.
Se uma etapa não se aplicar, escreva uma nota de uma linha ("nenhum any encontrado") para que os revisores saibam que você verificou.
Pare após as primeiras 3-5 etapas de alto impacto se você tiver um limite de tempo - a lista está ordenada por alavancagem.
Procure por: Qual arquivo é a entrada da rota (page.tsx, layout.tsx)? Quais filhos são Server Components ou Client Components? Onde aparece o primeiro "use client"?
Refatore quando:"use client" estiver no topo de um wrapper que renderiza conteúdo majoritariamente estático. Empurre a diretiva para a menor folha interativa. Cada kilobyte de marcação estática acima do limite é enviado como JS desnecessariamente.
// antes: a página inteira é cliente"use client";export default function Page() { return <Layout><Header /><Sidebar /><InteractiveChart /></Layout>;}// depois: apenas o gráfico é clienteexport default function Page() { return <Layout><Header /><Sidebar /><InteractiveChart /></Layout>;}// InteractiveChart.tsx -> "use client";
Procure por: O que cada arquivo faz em uma frase? Se você não consegue terminar a frase sem "e" ou "também", ele está fazendo muito.
Refatore quando: Um componente renderiza, busca dados, valida, formata E rastreia análises. Divida em partes focadas: um Server Component para dados, um Client Component para interação, utilitários para formatação.
Procure por: Onde cada pedaço de dado entra na árvore? Props, contexto, busca do servidor, parâmetro de rota, parâmetro de busca da URL, store?
Refatore quando: O mesmo valor é buscado em dois lugares, ou props são passadas por 3+ componentes intocadas (prop drilling). Mova a busca para um Server Component, ou eleve o estado para um provider colocado em conjunto, ou componha com children em vez de fazer drilling.
Procure por: Uma prop passada por 3+ camadas sem ser lida. Ou um componente aceitando 10+ props que são encaminhadas.
Refatore: Passe children para que o pai forneça a folha diretamente, ou envolva a subárvore em um provider de contexto com escopo para essa funcionalidade.
Procure por:useEffect(() => { fetch(...).then(setData) }, []) em um componente que não precisa do navegador.
Refatore: Converta o pai para um Server Component async e use await para os dados, ou use SWR / React Query para casos orientados pelo cliente. useEffect para busca de dados é quase sempre errado em código do App Router.
Procure por:<form onSubmit={...}> com fetch('/api/...') dentro do manipulador.
Refatore: Defina uma Server Action em actions.ts, vincule-a via <form action={submit}> e use useActionState para o estado pendente e de erro. Obtenha melhoria progressiva gratuita e sem desvios na validação do cliente.
Procure por: As mesmas 8-15 linhas de marcação repetidas em 2-3 arquivos (layout de card, estado vazio, bloco de erro).
Refatore: Extraia para um componente compartilhado na mesma pasta de funcionalidade. Não abstraia demais - se for usado duas vezes com intenção diferente, deixe como está.
Procure por:enum Status { ... } ou objetos com chaves de string fingindo ser enums.
Refatore:const STATUS = ['idle','loading','success'] as const; type Status = typeof STATUS[number];. Bundle menor, tipagem estrutural, sem objeto em tempo de execução.
Procure por: Dependências ausentes (aviso do lint), ou dependências instáveis (literais de objeto/função recriados a cada renderização, causando loops infinitos).
Refatore: Memoize a dependência instável com useMemo/useCallback, OU mova o valor para fora da renderização, OU colapse o efeito em um manipulador de eventos. Se o efeito for apenas sincronizar um valor, veja a etapa 14.
Procure por:cond1 ? a : cond2 ? b : cond3 ? c : d em JSX.
Refatore: Use switch em um campo status discriminado, ou use retornos antecipados: if (loading) return <Spinner />; if (error) return <Error />; return <Data />.
Procure por: Uma rota inteira caindo em um único spinner, ou um erro não capturado "branqueando" a página.
Refatore: Adicione loading.tsx por segmento de rota para streaming. Envolva subárvores de cliente arriscadas com <ErrorBoundary> (ou use error.tsx do Next.js) para que o resto da página sobreviva.
Procure por:document.getElementById, el.classList.add, chamadas manuais de foco/scroll espalhadas em manipuladores.
Refatore: Controle o comportamento a partir do estado e deixe o React renderizá-lo. Use ref + useEffect apenas para necessidades imperativas genuínas (gerenciamento de foco, bibliotecas de terceiros, medição de layout).
Procure por: Botões sem texto ou aria-label, controles apenas com ícones, htmlFor ausente, estado apenas por cor, alt ausente em <Image>.
Refatore: Cada elemento interativo precisa de um nome acessível. Cada imagem precisa de alt (string vazia para decorativa). Cada input de formulário precisa de um rótulo associado. Esta é a melhoria de UX mais barata da lista.
Cada etapa que você executou produziu um PR pequeno e revisável.
Cada etapa que você pulou tem uma nota de uma linha na descrição do PR ("etapa 12: nenhum enum nesta funcionalidade").
Execute o build, a suíte de testes e navegue pela funcionalidade no navegador antes de marcar a auditoria como concluída.
Se você encontrar um 21º padrão que se repete em toda a base de código, proponha adicioná-lo a esta lista - o checklist deve crescer com a base de código.
Revisado por Chris St. John·Última atualização: 7 de jul. de 2026