Saltar al contenido

Lección 4 de 12 · Lectura y práctica

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.

Del concepto a la práctica

Taller de esta lección

Un HOC añade una capacidad transversal sin modificar el componente recibido. Para que sea seguro, debe reenviar props, conservar una identidad descriptiva y documentar cuáles props controla y cuáles reenvía. En código nuevo conviene comparar esta complejidad con un hook o un Provider antes de adoptarlo.

Ejemplo resuelto

jsx
function withReadOnly(Wrapped) {
  function ReadOnly(props) {
    return <Wrapped {...props} canEdit={false} />;
  }
  ReadOnly.displayName = `withReadOnly(${Wrapped.displayName || Wrapped.name})`;
  return ReadOnly;
}

Si el componente recibe title:"Informe", conserva el título y obtiene canEdit=false.

Pruébalo

  1. Crea un componente que muestre title y canEdit.

  2. Envuélvelo con withReadOnly.

  3. Comprueba que el componente original no cambia y que la versión envuelta bloquea edición.

Comprueba tu resultado

Error frecuente: mutar Wrapped y añadirle propiedades directamente. Corrígelo devolviendo otro componente.

Ejercicio: pasa una prop role:"viewer" y verifica que aparece junto al título; el resultado esperado es una instancia nueva, con el original conservando su conducta inicial cuando recibe explícitamente canEdit=true.

withReadOnly impone canEdit=false en la presentación. La API debe volver a comprobar permisos antes de aceptar una escritura: un cliente puede llamar al endpoint sin pasar por el botón. Declara el HOC resultante fuera del cuerpo de render; cambiar su identidad en cada render puede remontar la vista y perder estado.

Este contrato sí sobrescribe intencionalmente canEdit con false al poner esa prop después de la propagación: una prop canEdit=true del consumidor no puede activar edición en la versión envuelta.

Capas de acceso, actualización, copias y respuesta a incidentes alrededor de un sistema.
CursaloMapa de práctica
La seguridad necesita varias capas

El control de acceso, las actualizaciones y las copias de seguridad cubren riesgos distintos. Una alerta necesita un procedimiento de respuesta para contener y recuperar el servicio. Varias capas reducen la exposición, pero ninguna garantiza seguridad absoluta.

Ver la infografía en tamaño completo ↗
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 (
      
    );
  };
};

// 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.

Sigue con React Intermedio: Patrones y Optimización

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.