Intermedio
Composición de componentes
Es un patrón de diseño de componentes que se basa en crear un componente padre con un solo objetivo, proporcionarle a sus hijos las propiedades necesarias para que se rendericen sin problemas.
Permite una estructura declarativa a la hora de construir nuevos componentes, además ayuda a la lectura del código por su simplicidad y limpieza.
Un ejemplo de este diseño sería una lista que renderiza los elementos hijos:
Esto seria una alternativa a usar React Context.
Colocación del estado
Máxima cercanía a la relevancia: El estado debe estar tan cerca como sea posible de donde lo estemos usando y actualizando.
Stateful vs stateless: Separar lógica y estado de componentes que manejan UI.
¿Dónde los guardamos? Este problema también se conoce como state colocation. Ejemplo:
Cuando varios componentes necesitan compartir los mismos datos de un estado, entonces se recomienda elevar ese estado compartido hasta su ancestro común más cercano.
Dicho de otra forma. Si dos componentes hijos comparten los mismos datos de su padre, entonces mueve el estado al padre en lugar de mantener un estado local en sus hijos.
Para entenderlo, lo mejor es que lo veamos con un ejemplo.
¿Qué pasa si queremos que el total de regalos se actualice cada vez que añadimos un regalo? Como podemos ver, no es posible porque el estado de totalGifts
está en el componente TotalGifts
y no en el componente GiftList
. Y como no podemos acceder al estado de GiftList
desde TotalGifts
, no podemos actualizar el estado de totalGifts
cuando añadimos un regalo.
Tenemos que subir el estado de gifts
al componente padre App
y le pasaremos el número de regalos como prop al componente TotalGifts
.
Con esto, lo que hemos hecho es elevar el estado. Lo hemos movido desde el componente GiftList
al componente App
. Ahora pasamos como prop los regalos al componente GiftList
y una forma de actualizar el estado, y también hemos pasado como prop al componente TotalGifts
el número de regalos.
Render Props
Es un patrón que nos permite compartir código teniendo un componente el cual recibe una función render(u otro nombre) vía props la cual será el render que ejecutará el componente. Ejemplo, tenemos esto:
La ventaja de el patrón Render props nos permite hacer codigo mas declarativo siendo mas especificos para saber:
Que vamos a renderizar
Cuando lo vamos a renderizar
Donde lo vamos a renderizar
La implementación quedaria así:
Usando Render Props
Usando Render Function
Tambien se pude substituir un render prop por un render function, la diferencia es que con function prop es que funtion envia en el children toda la lógica.
En React, los High Order Components (HOCs) y el patrón Render Props son dos patrones comunes para reutilizar la lógica entre componentes. Sin embargo, los HOCs pueden sufrir del "problema de colisión de nombres" cuando múltiples HOCs intentan pasar propiedades con el mismo nombre al componente envuelto. El patrón Render Props puede evitar este problema al delegar el control de la renderización y permitir al desarrollador elegir los nombres de las propiedades.
Ejemplo del Problema de Colisión con HOCs
Imaginemos que tenemos dos HOCs: uno para manejar el estado de autenticación y otro para manejar el estado de tema (tema claro u oscuro). Ambos HOCs podrían querer pasar una propiedad user
al componente envuelto.
HOC de Autenticación:
HOC de Tema:
Componente Envuelto:
Problema:
Cuando se renderiza EnhancedUserProfile
, el segundo HOC (withTheme
) sobrescribirá la propiedad user
pasada por el primer HOC (withAuth
). Esto resulta en un comportamiento inesperado, ya que el componente UserProfile
solo recibirá la última versión de user
, perdiendo así los datos de autenticación.
Solución con Render Props
El patrón Render Props evita este problema al permitir que el componente hijo controle cómo se reciben y usan las propiedades. En lugar de pasar propiedades directamente al componente envuelto, se pasa una función que recibe los datos necesarios.
Implementación con Render Props:
Render Props para Autenticación:
Render Props para Tema:
Componente que Consume Ambas Propiedades:
Explicación:
AuthProvider pasa
user
a su función hija.ThemeProvider pasa
theme
a su función hija.En el componente
UserProfile
, ambas propiedadesuser
ytheme
se reciben sin colisiones, porque el desarrollador decide cómo nombrarlas y usarlas dentro de la función de render.
Conclusión:
El patrón Render Props evita el problema de colisión de nombres en HOCs al proporcionar una mayor flexibilidad en cómo se pasan y se nombran las propiedades. Cada parte de la lógica puede exponer sus datos sin interferir con otras, lo que lleva a un código más claro y fácil de mantener.
React.Children y React.cloneElement
Se utiliza para poder pasar propiedades aparteque no están dentro de children a los componentes hijos de nuestros componentes contenedores por alguna circunstancia.
El problema es que cuando enviamos más de un componente o elemento hijo recibidas en las props del componente padre. CloneElement necesita recibir un elemento de react, cuando children es más de un componente entonces tenemos un array, para esto existe React.Children que nos ayuda a que CloneElement entienda sin importar cuantos elementos vienen en el props.children.
High Order Components (HOC)
Las funciones como las conocemos pueden devolvernos un valor en sus returns, pero estas funciones de "orden superior", son funciones que devuelven otras funciones (HOF).
Si llamamos a la High Order Function y le enviamos un parámetro no tendremos todavía un resultado, como está devolviendo otra función tenemos que llamar a esa función que obtenemos luego de llamar a la de orden superior, enviarle los nuevos parámetros que necesita la función de retorno y entonces si, obtendremos nuestro resultado.
Son funciones que retornan otras funciones aplicando el concepto funcional currying.
Debido a que los componentes son funciones podemos también aplicar este concepto.
De esta manera estamos personalizando varios aspectos del componente deseado, como:
Los parámetros de las funciones nos permiten configurar el componente que envuelve, las props
Podemos reutilizar los HOC
Ejemplos
Antes de retornar el componente en sí, hace una petición y entrega al componente esa información
Además que podemos personalizar el estado de carga
También podemos agregar más "capas" para tener más personalizaciones como por ejemplo
Esto nos permite poder extender funcionalidades.
HOCs
En React, un Higher-Order Component (HOC) es una función que toma un componente como argumento y devuelve un nuevo componente. Los HOCs son una forma avanzada de reutilizar la lógica de componentes entre múltiples componentes sin duplicar código.
¿Qué son y cómo funcionan los HOCs?
Un HOC es esencialmente una función que toma un componente WrappedComponent
y retorna un nuevo componente EnhancedComponent
. El HOC puede agregarle lógica, manejar props o estado, o ejecutar cualquier otro comportamiento adicional necesario, y luego pasarle los resultados al componente original.
En este ejemplo, withLogging
es un HOC que envuelve WrappedComponent
y agrega un mensaje de log en la consola cada vez que el componente se renderiza.
¿Para qué sirven los HOCs?
Los HOCs son útiles en varios escenarios, tales como:
Reutilización de lógica: Permiten compartir lógica entre componentes sin duplicar código.
Manipulación de props: Pueden modificar las props antes de que lleguen al componente envuelto.
Acceso a contextos: En aplicaciones anteriores a React Context, los HOCs facilitaban el acceso a datos compartidos.
Control de renderizado: Puedes condicionar la visualización de un componente, agregar un
loading
spinner o cualquier lógica relacionada con el renderizado.
Ejemplo de uso: Autorización
Supongamos que quieres restringir el acceso a una página en función del rol del usuario:
Aquí, el HOC withAuthorization
envuelve SomeComponent
y restringe su acceso si el usuario no tiene el rol de administrador.
¿Siguen siendo útiles los HOCs?
Hoy en día, los HOCs no se utilizan tan frecuentemente como antes, especialmente desde la introducción de React Hooks y Context API en versiones recientes de React. Las Hooks permiten manejar lógica compartida sin tener que recurrir a un HOC. Esto ha llevado a una reducción significativa en el uso de HOCs para tareas como la gestión de estado, el acceso a contextos y otras funciones compartidas.
¿Cuándo son estrictamente necesarios los HOCs?
Integración con librerías antiguas: Algunos paquetes y librerías (como React-Redux antes de
useSelector
yuseDispatch
) aún ofrecen HOCs para inyectar funcionalidades en los componentes.Legacy code: En aplicaciones más antiguas, los HOCs pueden seguir siendo la mejor manera de implementar ciertas funcionalidades sin una gran refactorización.
Render Props: Aunque también en desuso frente a Hooks, los HOCs pueden complementar o reemplazar la lógica de componentes de Render Props.
Resumen
Los HOCs fueron una herramienta esencial para la reutilización de lógica en React antes de la introducción de los Hooks, pero hoy en día, la mayoría de las funcionalidades que implementan pueden ser logradas con Hooks y Context API, que son más fáciles de entender y más eficientes. Sin embargo, siguen siendo útiles para integrar componentes de librerías antiguas y en aplicaciones legacy donde los Hooks podrían requerir una refactorización extensa.
Render props vs. High Order Components vs. React Hooks
Maquetación
Al utilizar React hooks
, estos nos proveen propiedades, información y actualizadores para que luego en el return de nuestros componentes podamos validaciones y renderizar o no ciertos componentes.
Pero cuando aplicamos Render props
dejamos de tener las validaciones y los componentes en el mismo lugar. Es decir, pasamos las validaciones al componente en cuestión, y simplemente debemos de enviar nuestros componentes a sus render props correspondientes. .
Ambas son formas muy correctas y comunes de trabajar, pero las render props son mucho más cómodas y ordenadas.
Share data
Empezando por las Render functions
, estas nos permiten compartir información con funciones que en sus parámetros nos dejan esa información que necesitábamos que nos compartieran.
Pero si necesitamos demasiada información de distintas render functions para un mismo componente ya no es adecuado y tendríamos código espagueti. Así que tiene poca escalabilidad.
Los High Order Components
, son funciones que devuelven otras funciones de esa manera sucesivamente hasta retornar un componente de React al que podamos pasarle toda nuestra información.
Sin embargo, si necesitamos la información de muchos hooks en un mismo componente entonces se tiene el mismo problema de antes, código muy horizontal lo que significa que no es escalable.
Los React hooks
, solo lo llamamos y luego consumimos la información en el return de nuestro componente.
Si tenemos muchos llamados a distintos react hooks nuestro código sigue siendo extremadamente vertical y fácil de leer sin importar de cuantos react hooks estemos llamando. .
Lo ideal para estos casos son los React Hooks o tambien los custom hooks, aunque hay manera de hacerlo tambien con HOC tambien debido a que se puede mejorar la legibilidad con la función compose.
Last updated