Entendendo componentes de ordem superior no React com exemplos

Componentes de ordem superior (HOCs) são um padrão no React que pode ser confuso no início, mas uma vez compreendidos, tornam-se uma ferramenta valiosa para abstrair e reutilizar a lógica de componentes. Neste guia, você aprenderá o que são HOCs, como usá-los e quando eles fazem sentido — com exemplos claros ao longo do caminho.
Principais Aprendizados
- Entenda o que é um componente de ordem superior no React
- Aprenda como escrever e usar HOCs com exemplos claros de código
- Saiba quando usar HOCs — e quando não usar
O que é um componente de ordem superior?
Um componente de ordem superior é uma função que recebe um componente e retorna um novo componente. Ele adiciona comportamento, props ou lógica ao componente original — sem modificá-lo diretamente.
Estrutura básica
const withExtraLogic = (Component) => {
return function WrappedComponent(props) {
// Adicione comportamento personalizado aqui
return <Component {...props} />;
};
};
Pense nisso como um decorador: você envolve algo e o aprimora antes de passá-lo adiante.
Por que usar um HOC?
- Reutilização de código: Abstrai lógica repetida
- Preocupações transversais: Registro, autenticação, rastreamento
- Injeção de props: Injeta props com base em lógica sem sobrecarregar os internos do componente
Exemplo básico: withLogger
const withLogger = (Component) => {
return function WrappedComponent(props) {
useEffect(() => {
console.log('Montado:', Component.name);
}, []);
return <Component {...props} />;
};
};
const Hello = () => <h1>Hello</h1>;
const LoggedHello = withLogger(Hello);
// Uso
<LoggedHello />
Isso registra o nome do componente quando ele é montado — sem tocar no componente Hello
original.
Outro caso de uso: withWindowWidth
Este HOC adiciona a largura da janela como uma prop para qualquer componente:
const withWindowWidth = (Component) => {
return function WrappedComponent(props) {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return <Component {...props} windowWidth={width} />;
};
};
const DisplayWidth = ({ windowWidth }) => <p>Width: {windowWidth}px</p>;
const ResponsiveDisplay = withWindowWidth(DisplayWidth);
Isso permite criar um componente responsivo sem duplicar a lógica de redimensionamento.
HOCs vs hooks vs render props
Padrão Descrição Use quando… HOC Função retornando um novo componente Você quer adicionar comportamento a muitos componentes Hook Função reutilizável usando use*
Você quer lógica de estado reutilizável Render props Passa uma função como filho Você quer renderização dinâmica via função
Comparação detalhada com hooks
Hooks são preferidos para compartilhamento de lógica hoje, mas há diferenças:
- HOCs são invólucros externos. Hooks são executados dentro do componente.
- Hooks oferecem composabilidade — você pode chamar múltiplos hooks em um componente facilmente.
- Hooks funcionam com refs e estado local naturalmente, enquanto HOCs precisam de cuidados especiais para encaminhamento de
ref
.
Mesma lógica, implementação diferente
Usando um hook em vez de withWindowWidth
:
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
const DisplayWidth = () => {
const width = useWindowWidth();
return <p>Width: {width}px</p>;
};
Esta versão evita o invólucro extra e é mais legível no React moderno.
Limitações dos HOCs
- Aninhamento de invólucros: Muitos HOCs podem tornar a árvore de componentes difícil de depurar
- Nomenclatura: Componentes invólucros anônimos dificultam a leitura nas DevTools
- Encaminhamento de ref: Refs padrão não funcionam a menos que você use
forwardRef
Exemplo de problema com ref
const withWrapper = (Component) => (props) => <Component {...props} />;
const FancyInput = forwardRef((props, ref) => <input ref={ref} {...props} />);
Sem forwardRef
, ref
apontaria para o invólucro, não para o input real.
Melhores práticas
- Sempre passe props adiante:
<Component {...props} />
- Nomeie seus componentes envolvidos para depuração:
WrappedComponent.displayName = `withLogger(${Component.displayName || Component.name})`;
- Evite HOCs quando hooks podem fazer o trabalho de forma mais clara
Conclusão
Componentes de ordem superior são uma maneira flexível de estender e reutilizar a lógica de componentes. Embora os hooks sejam mais comuns no React moderno, os HOCs ainda têm seu lugar — especialmente quando você deseja adicionar lógica em torno de componentes existentes sem alterar seus internos. Use-os quando eles tornam seu código mais claro, não mais complexo.
Perguntas Frequentes
Sim, embora sejam menos comuns agora. Hooks substituíram muitos casos de uso, mas HOCs ainda são úteis para injetar comportamento em múltiplos componentes.
Um HOC envolve um componente e retorna um novo. Um hook é uma função que adiciona lógica a um componente a partir de dentro.
Apenas se você encaminhar a ref usando `forwardRef`. Caso contrário, as refs apontarão para o invólucro em vez do componente original.
Use HOCs quando quiser envolver muitos componentes com a mesma lógica externa, como autenticação ou registro, sem reescrever essa lógica repetidamente.