Comprender cómo una función puede devolver otra función es la base para dominar uno de los patrones más poderosos en React. Los high order components (HOC) permiten inyectar propiedades, datos de APIs y lógica reutilizable a cualquier componente, sin modificar su estructura interna. Todo parte de un concepto fundamental de programación funcional: el currying.
¿Qué es el currying y por qué importa en React?
Antes de hablar de componentes, hay que entender las high order functions [0:06]. Son funciones que, en lugar de devolver un valor común, retornan otra función. Esa función de retorno se comporta como cualquier función normal de JavaScript: recibe parámetros y devuelve resultados.
Un ejemplo clásico es el de la suma [0:36]:
- La high order function recibe el primer número.
- La función de retorno recibe el segundo número.
- Solo al llamar a ambas funciones obtenemos el resultado.
Lo interesante es que podemos guardar en una variable el llamado a la primera función y reutilizarla varias veces con distintos segundos parámetros [1:06]. Esto es currying: dividir una función con múltiples parámetros en una cadena de funciones que reciben un parámetro a la vez.
Si es la primera vez que te encuentras con este concepto, es normal que resulte confuso. El currying se estudia dentro de la programación funcional [1:24], y dominarlo antes de trabajar con frameworks o librerías de JavaScript marca una diferencia enorme.
¿Cómo se convierten las high order functions en high order components?
El salto conceptual es directo: los componentes de React también son funciones [1:48]. Entonces, una función que devuelve un componente de React es un high order component.
¿Qué papel juega el wrapped component?
La clave está en que nuestra función HOC recibe como parámetro un componente, conocido como wrapped component [2:06]. El componente de retorno puede:
- Pasarle nuevas propiedades al wrapped component.
- Renderizarlo junto con otros componentes.
- Mostrarlo o no según alguna condición.
Por ejemplo, si un componente llamado TodoBox necesita una propiedad especial, en lugar de enviársela manualmente desde el componente padre, envolvemos TodoBox dentro del HOC [2:30]. Automáticamente recibe esa propiedad solo por haber pasado por el high order component.
¿Cómo funciona un HOC con llamadas a una API?
Un caso muy práctico es crear un HOC llamado withAPI [3:18]. Esta función:
- Recibe un wrapped component.
- Realiza una petición a una API antes de retornarlo.
- Entrega toda la información obtenida como propiedades al componente.
- Mientras carga, puede mostrar un estado de carga: un párrafo, un loading skeleton o lo que necesites.
Cualquier componente que necesite datos de esa API solo debe pasar por withAPI y los recibe automáticamente [3:42].
¿Se pueden encadenar múltiples high order components?
Sí, y aquí es donde el patrón se vuelve realmente potente [3:54]. Podemos envolver funciones dentro de funciones sin límite. Algunos ejemplos prácticos:
- Permitir que cada componente defina la URL de la API desde donde cargar sus datos [4:06].
- Crear HOCs para inyectar propiedades del usuario, datos filtrados de búsqueda o información persistida en local storage [4:30].
- Pasar un componente por
withTodos, luego por withUser, y obtener la información de ambos HOCs combinada [4:48].
La implementación sigue siendo sencilla: maquetas tu componente, lo envuelves en el HOC, le pasas los parámetros necesarios y recibes todas las propiedades inyectadas de forma automática.
El encadenamiento puede extenderse tanto como lo necesites: withTodos, luego withFilters, luego withUser [5:06]. Cada HOC agrega su propia capa de datos o lógica sin que el componente original se modifique.
¿Ya habías trabajado con high order components o es la primera vez que te encuentras con este patrón? Comparte tu experiencia y las dudas que te hayan surgido.