Prop Drilling: Como Evitar com o Composition Pattern em React

Prop Drilling: Como Evitar com o Composition Pattern em React






Evitando Prop Drilling com o Pattern de Composition



Evitando Prop Drilling com o Pattern de Composition

Como desenhar componentes React de forma mais limpa, mantendo responsabilidades separadas e evitando passagem excessiva de props.

1) Contextualizando o problema: prop drilling e seus impactos

Prop drilling ocorre quando precisamos passar props por várias camadas de componentes para alcançar um componente filho que realmente
utiliza aquele dado ou comportamento. Mesmo que a API pareça simples, esse padrão aumenta acoplamento, dificulta a reutilização
e torna a manutenção dolorosa conforme a base de código cresce.

A ideia que defendo é reduzir esse acoplamento deslocando a responsabilidade de composição para padrões que permitem
construir componentes através de unidades menores e combináveis, sem que cada camada precise conhecer a pilha de props de cima para baixo.

2) O que é o pattern de composition?

O pattern de composition foca em criar componentes que são, por natureza, composáveis. Em vez de passar props
para todos os níveis, você monta a interface a partir de partes menores (slots) que assumem responsabilidade de
renderização. Em React, isso se materializa via:

  • Componentes com subcomponentes (slots) como Header, Body, Footer.
  • Render props ou funções passadas como filhos para fornecer conteúdo sob demanda.
  • Padrões de ergonomia como as prop e composição baseada em funções para extensões sem quebrar o encapsulamento.

Dica prática: prefira compor a UI com partes independentes, em vez de passar muitas props profundas.

3) Como aplicar: padrões de composição na prática

Abaixo apresento duas formas eficazes de evitar prop drilling com o pattern de composition:

  1. Slots/padrão de subcomponentes estáticos:

    Crio um componente base que expõe partes específicas para serem preenchidas pelos filhos, mantendo a API enxuta.
  2. Render props simplificadas para conteúdo dinâmico:

    Permito que o usuário forneça conteúdo via props ou via filhos, sem exigir que passe props de estado por várias camadas.

// Exemplo 1: Card com slots (Header, Body, Footer)
function Card({ children }) {
  return 
{children}
; } Card.Header = function CardHeader({ children }) { return
{children}
; } Card.Body = function CardBody({ children }) { return
{children}
; } Card.Footer = function CardFooter({ children }) { return
{children}
; }; // Uso: <Card> <Card.Header>Título do Card</Card.Header> <Card.Body>Conteúdo interno que não faz parte da API externa</Card.Body> <Card.Footer> <button>Ação</button> </Card.Footer> </Card>

// Exemplo 2: Pattern "Modal" com composição
function Modal({ children }) {
  return (
    <div role="dialog" aria-modal="true" className="modal">
      {children}
    </div>
  );
}
Modal.Header = function ModalHeader({ children }) {
  return <div className="modal-header">{children}</div>;
};
Modal.Body = function ModalBody({ children }) {
  return <div className="modal-body">{children}</div>;
};
Modal.Footer = function ModalFooter({ children }) {
  return <div className="modal-footer">{children}</div>;
};

// Uso:
<Modal>
  <Modal.Header>Confirmação</Modal.Header>
  <Modal.Body>Deseja realmente prosseguir com esta ação?</Modal.Body>
  <Modal.Footer>
    <button>Cancelar</button>
    <button>Confirmar</button>
  </Modal.Footer>
</Modal>
      

4) Benefícios, trade-offs e boas práticas

Aplicar o pattern de composition traz ganhos claros:

  • Menor acoplamento entre camadas; cada componente expõe apenas o necessário.
  • Reutilização mais simples: é possível combinar componentes de maneiras novas sem refatorar props existentes.
  • Melhor legibilidade da UI: estrutura fica explícita pela composição de partes, não pela passagem de props profundas.

Atenção a trade-offs: a flexibilidade adicional pode exigir mais planejamento inicial no design de APIs, e algumas combinações
podem exigir documentação clara sobre as possibilidades de composição.

Conclusão rápida

O pattern de composition é uma ferramenta poderosa para evitar prop drilling e manter componentes pequenos, coesos e
fáceis de testar. Ao oferecer slots para composição de partes da UI e usar render props de forma contida, você cria
uma base que cresce de forma sustentável sem perder clareza.

Personalize os padrões conforme o seu ecossistema: React, Preact ou outras libs de view podem se beneficiar de estruturas
semelhantes de composição.

Quer se aprofundar? Leia outros posts sobre padrões de composição, gerenciamento de estado local e ergonomia de APIs.

Leia mais posts

Sugestões de leitura