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.