Padrões Avançados em React: Compound Components, Render Props e HOCs na Prática Já leu

Compound Components Compound Components é um padrão onde componentes trabalham em conjunto para gerenciar estado compartilhado. Cada componente filho é simples, mas juntos formam uma unidade funcional completa. Este padrão melhora a legibilidade do código e oferece flexibilidade sem expor lógica complexa. O segredo está em usar ou Context API para compartilhar estado entre componentes irmãos. Veja um exemplo prático de um componente de Acordeão: A vantagem é que o usuário controla a estrutura HTML sem lidar com props complexas. Mantém a interface clara e intuitiva. Render Props Render Props é uma técnica onde um componente recebe uma função como prop, que retorna JSX. Essa função tem acesso ao estado interno do componente, permitindo máxima flexibilidade sem precisar criar componentes derivados. É especialmente útil para compartilhar lógica entre componentes que renderizam de formas diferentes. Aqui está um exemplo de um componente que gerencia estado de mouse: O padrão oferece total controle sobre como os dados são renderizados. Porém, pode levar

Compound Components

Compound Components é um padrão onde componentes trabalham em conjunto para gerenciar estado compartilhado. Cada componente filho é simples, mas juntos formam uma unidade funcional completa. Este padrão melhora a legibilidade do código e oferece flexibilidade sem expor lógica complexa.

O segredo está em usar React.cloneElement ou Context API para compartilhar estado entre componentes irmãos. Veja um exemplo prático de um componente de Acordeão:

const Accordion = ({ children }) => {
  const [activeId, setActiveId] = React.useState(null);

  return (
    <div className="accordion">
      {React.Children.map(children, child =>
        React.cloneElement(child, { activeId, setActiveId })
      )}
    </div>
  );
};

const AccordionItem = ({ id, title, children, activeId, setActiveId }) => {
  const isActive = activeId === id;

  return (
    <div className="accordion-item">
      <button onClick={() => setActiveId(isActive ? null : id)}>
        {title}
      </button>
      {isActive && <div className="accordion-content">{children}</div>}
    </div>
  );
};

// Uso
<Accordion>
  <AccordionItem id="1" title="Seção 1">Conteúdo 1</AccordionItem>
  <AccordionItem id="2" title="Seção 2">Conteúdo 2</AccordionItem>
</Accordion>

A vantagem é que o usuário controla a estrutura HTML sem lidar com props complexas. Mantém a interface clara e intuitiva.

Render Props

Render Props é uma técnica onde um componente recebe uma função como prop, que retorna JSX. Essa função tem acesso ao estado interno do componente, permitindo máxima flexibilidade sem precisar criar componentes derivados. É especialmente útil para compartilhar lógica entre componentes que renderizam de formas diferentes.

Aqui está um exemplo de um componente que gerencia estado de mouse:

const MouseTracker = ({ children }) => {
  const [position, setPosition] = React.useState({ x: 0, y: 0 });

  const handleMouseMove = (e) => {
    setPosition({ x: e.clientX, y: e.clientY });
  };

  return (
    <div onMouseMove={handleMouseMove} style={{ height: '100vh' }}>
      {children(position)}
    </div>
  );
};

// Uso
<MouseTracker>
  {({ x, y }) => (
    <div>
      Posição do mouse: X={x}, Y={y}
      <div style={{ left: x, top: y, position: 'absolute' }}>🎯</div>
    </div>
  )}
</MouseTracker>

O padrão oferece total controle sobre como os dados são renderizados. Porém, pode levar ao "callback hell" se mal estruturado. Use Render Props quando precisar de máxima flexibilidade de renderização.

Higher-Order Components (HOCs)

Um HOC é uma função que recebe um componente e retorna um novo componente aprimorado com funcionalidade adicional. É um padrão poderoso para reutilizar lógica, mas deve ser usado com cuidado pois pode complicar a rastreabilidade de props. Ideal para adicionar comportamentos transversais como autenticação ou temas globais.

Veja um exemplo prático de HOC para autenticação:

const withAuth = (WrappedComponent) => {
  return (props) => {
    const [isAuthenticated, setIsAuthenticated] = React.useState(false);

    React.useEffect(() => {
      // Simular verificação de autenticação
      const token = localStorage.getItem('authToken');
      setIsAuthenticated(!!token);
    }, []);

    if (!isAuthenticated) {
      return <div>Acesso negado. Faça login primeiro.</div>;
    }

    return <WrappedComponent {...props} />;
  };
};

const Dashboard = () => <h1>Bem-vindo ao Dashboard</h1>;
const ProtectedDashboard = withAuth(Dashboard);

// Uso
<ProtectedDashboard />

HOCs funcionam bem para lógica transversal, mas a composição de múltiplos HOCs pode criar problemas de performance e readability. Considere usar Hooks customizados como alternativa mais moderna.

Comparação: Quando Usar Cada Um

  • Compound Components: Interface clara, múltiplos componentes relacionados, máximo controle estrutural.
  • Render Props: Compartilhar estado dinamicamente, diferentes formas de renderizar dados.
  • HOCs: Adicionar funcionalidade a componentes existentes, lógica transversal como logging ou autenticação.

O React moderno privilegia Custom Hooks sobre esses padrões, mas todos ainda têm casos de uso válidos. A escolha depende da complexidade, legibilidade e manutenibilidade do seu projeto.

Conclusão

Os três padrões avançados em React—Compound Components, Render Props e HOCs—oferecem formas elegantes de gerenciar complexidade. Compound Components priorizam clareza estrutural; Render Props oferecem máxima flexibilidade; HOCs adicionam funcionalidade transversal. Domine-os não para usá-los em tudo, mas para escolher a solução certa em cada contexto. Na prática moderna, combine com Custom Hooks para código mais legível e eficiente.

Referências


Artigos relacionados