rochasolutions
Arquitetura

Arquitetura React: Como Estruturar um Projeto que Escala

Danilo Rocha5 min de leitura

O que é arquitetura React

Arquitetura React é o conjunto de decisões sobre como o código de uma aplicação se organiza: onde cada arquivo mora, como as camadas se comunicam e quais regras determinam se algo é componente, hook ou serviço. Nenhum framework ou biblioteca impõe essa divisão sozinho. Ela é o resultado de escolhas do time sobre como separar lógica de negócio, dados e interface.

Um projeto React sem arquitetura definida costuma funcionar bem nos primeiros meses. O problema aparece depois, quando o time cresce, o número de telas passa de vinte e cada novo desenvolvedor demora dias só para entender onde adicionar uma função. Nesse ponto, a pasta components já tem duzentos arquivos sem nenhuma hierarquia, e ninguém sabe mais qual componente depende de qual.

Organização por feature ou por tipo de arquivo

Organizar por feature agrupa tudo que uma funcionalidade usa, componente, hook, serviço e teste, dentro de uma única pasta. Organizar por tipo de arquivo separa por categoria técnica: uma pasta components, outra hooks, outra services, cada uma com arquivos de features diferentes misturados.

A organização por tipo parece limpa no início, porque segue uma convenção visual simples. O custo aparece quando alguém precisa mexer na feature de checkout: o componente está em components, o hook que busca o carrinho está em hooks, a chamada de API está em services, e o teste está numa quarta pasta. Editar uma funcionalidade vira um exercício de abrir cinco pastas diferentes para lembrar onde cada parte ficou.

A organização por feature resolve isso agrupando por proximidade de uso, não por categoria técnica:

src/
  features/
    checkout/
      Checkout.tsx
      useCarrinho.ts
      checkoutService.ts
      Checkout.test.tsx
    perfil/
      Perfil.tsx
      usePerfil.ts
      perfilService.ts
  components/
    Button.tsx
    Card.tsx

A pasta components na raiz sobra só para o que é genérico de verdade: botão, card, input, qualquer coisa reutilizada por mais de uma feature. Tudo que pertence a uma única funcionalidade fica dentro dela. Quando a feature de checkout for descontinuada, a pasta inteira sai junto, sem deixar arquivo órfão espalhado pelo projeto.

Camadas: separando lógica, dados e apresentação

Uma camada de apresentação, uma de estado e uma de acesso a dados evitam que a lógica de negócio fique presa dentro do componente visual. Isso é o que permite testar a regra sem precisar renderizar tela, e trocar a fonte de dados sem tocar no JSX.

Na prática, isso significa três tipos de arquivo dentro de cada feature. O componente cuida só de renderizar o que recebe e disparar eventos. O hook customizado guarda o estado e a lógica que decide o que mostrar, como validação de formulário ou regra de negócio. O serviço isola a chamada HTTP ou de banco, sem saber nada sobre React.

Esse tipo de separação é o motivo pelo qual gerenciamento de estado em React importa tanto quanto a arquitetura de pastas: um hook de estado bem isolado pode trocar de useState para uma biblioteca externa sem que nenhum componente precise mudar uma linha.

O sinal de que a separação está funcionando é simples: dá para ler o componente e entender o que a tela mostra, sem precisar saber de onde vem o dado. E dá para ler o serviço sem precisar saber em qual tela ele é usado.

Como estruturar um projeto React do zero

Definir a arquitetura antes de escrever a primeira tela evita boa parte da reorganização que costuma aparecer depois de seis meses de projeto.

  1. Defina a pasta raiz de features antes de criar qualquer componente. Toda funcionalidade nova nasce dentro dela, nunca solta em components.
  2. Separe o que é genérico do que é específico. Um componente só vai para a pasta compartilhada quando pelo menos duas features diferentes precisarem dele.
  3. Escreva o serviço de dados sem importar nada do React. Se o serviço importa useState ou useEffect, a camada está misturada.
  4. Coloque o teste ao lado do arquivo que ele testa, dentro da mesma pasta de feature, para que mudar a funcionalidade e mudar o teste seja um único gesto.
  5. Documente, num arquivo curto na raiz do projeto, a regra de onde cada tipo de arquivo mora. Isso evita que cada desenvolvedor novo invente a própria convenção.
  6. Revise a estrutura a cada trimestre. Uma feature que cresceu demais pode precisar virar duas, e isso só fica claro olhando o projeto de fora, não durante a correria de uma sprint.

Erros comuns de arquitetura React em projetos que crescem

O erro mais frequente é a pasta utils que vira depósito de tudo que não tem lugar óbvio. Com o tempo, ela acumula funções sem relação nenhuma entre si, e ninguém sabe mais buscar ali primeiro. Se uma função só serve a uma feature, ela deveria morar dentro da pasta dessa feature, não num arquivo genérico de utilidades.

Outro erro é criar abstração cedo demais. Um contexto global, uma camada de injeção de dependência ou um padrão de design elaborado fazem sentido quando o problema que resolvem já apareceu duas ou três vezes no projeto. Antes disso, a abstração custa mais tempo de manutenção do que resolve, porque ninguém sabe ainda qual é a forma certa do problema.

O terceiro é deixar a chamada de API dentro do componente, direto no useEffect. Isso parece mais rápido de escrever no primeiro momento, mas amarra a tela à origem do dado. Se depois o mesmo dado precisar vir de outro endpoint, ou for reaproveitado em outra tela, a lógica precisa ser copiada em vez de reutilizada.

Uma arquitetura React boa garante que qualquer pessoa do time, inclusive uma que entrou ontem, consiga prever onde um arquivo mora só olhando o nome da feature. A estrutura de pastas específica importa menos do que essa previsibilidade. Se o seu projeto já passou do ponto em que isso é verdade, fale com a gente para revisar a arquitetura antes que a reorganização fique mais cara do que é hoje.