React Intermedio: Patrones y Optimización

High Order Components: Envolviendo Funcionalidad

CONCEPTO CLAVE: Un High Order Component (HOC) es una función que recibe un componente y devuelve un nuevo componente con funcionalidad adicional. No es un componente en sí mismo, sino un patrón que envuelve otros componentes para compartir lógica. ¿Qué problema resuelven los HOC? Imaginemos que tenemos tres componentes que necesitan datos de autenticación. Sin HOC, repetiríamos la lógica de autenticación en cada componente. Con un HOC, envolvemos cada componente y automáticamente obtienen acceso
Tiempo de estudio
25 Min
CONCEPTO CLAVE: Un High Order Component (HOC) es una función que recibe un componente y devuelve un nuevo componente con funcionalidad adicional. No es un componente en sí mismo, sino un patrón que envuelve otros componentes para compartir lógica.


¿Qué problema resuelven los HOC?



Imaginemos que tenemos tres componentes que necesitan datos de autenticación. Sin HOC, repetiríamos la lógica de autenticación en cada componente. Con un HOC, envolvemos cada componente y automáticamente obtienen acceso a la información de usuario.



📌 Regla de oro: Los HOC nunca deben modificar el componente original. Solo lo envuelven y le pasan props adicionales.


Sintaxis básica de un HOC



La estructura fundamental de un HOC sigue este patrón:



const withHOC = (WrappedComponent) => {
return function(props) {
// Lógica adicional aquí
const nuevaProp = 'dato inyectado';

return ;
}
};

// Uso
const ComponenteMejorado = withHOC(ComponenteOriginal);


💡 Tip profesional: Por convención, los HOC deben empezar con with. Así withAuth, withTheme, withData comunican inmediatamente su propósito.


HOC con Estado y Efectos



El verdadero poder de los HOC aparece cuando necesitamos compartir estado o lifecycle methods entre múltiples componentes:



import { useState, useEffect } from 'react';

const withMouseTracker = (WrappedComponent) => {
return function ConMouseTracker(props) {
const [position, setPosition] = useState({ x: 0, y: 0 });

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

window.addEventListener('mousemove', handleMouseMove);
return () => window.removeEventListener('mousemove', handleMouseMove);
}, []);

return (
mousePosition={position}
{...props}
/>
);
};
};

// Componente que usa el HOC
const PanelEstadistico = ({ mousePosition, titulo }) => (

{titulo}


Posición del mouse: X={mousePosition.x}, Y={mousePosition.y}



);

const PanelMejorado = withMouseTracker(PanelEstadistico);


⚠️ Advertencia importante: Cuando uses HOC con hooks, recuerda que el HOC debe ser una función que retorna un componente funcional. No intentes usar hooks directamente en el HOC sin envolverlos en un componente funcional.


Pasos para crear un HOC robusto




  1. Identifica la lógica repetida: Busca código que copies entre componentes similares.

  2. Crea la función HOC: Debe recibir el componente y retornar uno nuevo con las props adicionales.

  3. Pasa las props correctamente: Usa el spread operator para mantener las props originales.

  4. Considera las props omitidas: Si el HOC consume props internas,Documenta esas props en el nombre o propTypes.

  5. Agrega displayName: Facilita el debugging en React DevTools.



HOC con Múltiples Parámetros



Los HOC pueden recibir parámetros adicionales para configurarlos dinámicamente:



const withAuth = (WrappedComponent, opciones = {}) => {
const { requiereAdmin = false } = opciones;

return function ConAuth(props) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
verificarAuth().then((userData) => {
setUser(userData);
setLoading(false);
});
}, []);

if (loading) return
Cargando...
;

if (requiereAdmin && !user?.esAdmin) {
return
Acceso denegado
;
}

return ;
};
};

// Uso con configuración
const DashboardAdmin = withAuth(Dashboard, { requiereAdmin: true })(Dashboard);


📌 Esta técnica de doble invocación se llama currying y permite configuraciones flexibles.


Display Name para Debugging



En React DevTools, los componentes HOC pueden aparecer sin nombre. Corrige esto:



const withData = (WrappedComponent) => {
function ConData(props) {
// lógica...
return ;
}

ConData.displayName = `withData(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;

return ConData;
};


💡 Sin displayName, verás solo "ConData" en DevTools, lo que dificulta identificar qué componente es cada uno.


HOC vs Render Props vs Hooks






































Criterio HOC Render Props Hooks
Reutilización Excelente Buena Excelente
Complejidad Media Baja Baja
Props naming Puede entrar en conflicto Control total Control total
Estilo dominante Clásico Legacy Moderno


⚠️ Nota de transición: En proyectos nuevos, los hooks suelen ser preferidos. Sin embargo, entender HOC es esencial para mantener código legacy y frameworks como Redux connect().


HOC Real: withLoading



Un HOC práctico que muestra estados de carga:



const withLoading = (WrappedComponent) => {
return function ConLoading({ isLoading, error, ...props }) {
if (error) {
return (

Error al cargar


{error.message}




);
}

if (isLoading) {
return (


Cargando...



);
}

return ;
};
};

// Componente limpio
const ListaUsuarios = ({ usuarios }) => (

    {usuarios.map(u =>
  • {u.nombre}
  • )}

);

// Envuelto con loading
const ListaUsuariosConLoading = withLoading(ListaUsuarios);

// Uso: automáticamente maneja loading y error
<ListaUsuariosConLoading
isLoading={cargando}
error={error}
usuarios={usuarios}
/>


Los HOC son como trajes a la medida: envuelven tu componente existente con nuevas capacidades sin alterar el traje original.


Composición de HOC



Puedes encadenar múltiples HOC para combinar funcionalidades:



const App = withAuth(
withTheme(
withLoading(
Dashboard
)
)
);

// O con composición:
const compose = (...hocs) => (Component) =>
hocs.reduce((acc, hoc) => hoc(acc), Component);

const App = compose(
withAuth,
withTheme,
withLoading
)(Dashboard);


💡 Esta técnica de compose viene de librerías como Redux (connect) y Lodash (flow). Hace el código más legible cuando tienes muchos HOC.


Cosas a Evitar




Ver más


  • No modifiques el componente original: No uses React.cloneElement paramutarlo.

  • No uses refs en props: Las refs no se pasan como props normales. Usa forwardRef si necesitas refs.

  • No copies props estáticas: Si el componente original tiene métodos estáticos, debes copiarlos manualmente.



// ❌ Incorrecto
const withEjemplo = (WrappedComponent) => {
return class extends React.Component {
render() {
const { exclude, ...props } = this.props;
return ;
}
};
};

// ✅ Correcto con forwardRef
const withEjemplo = (WrappedComponent) => {
function ConEjemplo(props, ref) {
return ;
}
return React.forwardRef(ConEjemplo);
};




Resumen Práctico



Los High Order Components siguen el principio de composición sobre herencia. Son ideales para:




  • Compartir lógica de acceso a datos

  • Inyectar props transversales (tema, auth, locale)

  • Wrapper visuales (loading, error, wrapper de portal)

  • Componentes con características comunes reutilizables



📌 Recuerda: Los HOC añaden componentes extra al árbol de React. En rendimiento crítico, considera hooks o memoización.



🧠 Quiz

¿Cuál es la principal ventaja de usar HOC sobre copiar y pegar código en múltiples componentes?



  • A) Los HOC hacen que el código sea más rápido

  • B) Los HOC permiten compartir lógica sin modificar los componentes originales

  • C) Los HOC eliminan la necesidad de props

  • D) Los HOC son más fáciles de escribir que hooks


✅ Respuesta correcta: B. Los HOC envuelven componentes existentes para compartir funcionalidad, manteniendo los componentes originales limpios y reutilizables.



En la próxima lección exploraremos cómo los HOC se comparan con los Render Props y cuándo elegir cada patrón según el contexto de tu aplicación.

Texto Leccion 4/12
Estas viendo
High Order Components: Envolviendo Funcionalidad
Hablar por WhatsAppContactar por WhatsApp