Aprende a crear componentes flexibles y mantenibles en React con los patrones render props y composition. Verás cómo un componente padre delega el “cómo se pinta” al hijo mediante una función, maximizando la reutilización de lógica y reduciendo código, con tipado sólido en TypeScript. Además, se explican ventajas, desventajas y cómo evitar errores comunes como el prop drilling.
¿Qué es render props y por qué mejora la reutilización?
El patrón render props consiste en pasar una función como prop para decidir el renderizado. Así, el padre controla la salida visual y el hijo solo expone datos o estado. Este enfoque aporta flexibilidad, mantenibilidad y reutilización al separar la lógica del diseño.
¿Cómo funciona el primer ejemplo con función render?
Dos componentes: parent component y child component.
El hijo recibe una prop función llamada render que retorna un elemento JSX.
El hijo define un nombre, por ejemplo, "DevCode", y llama a render(nombre).
El padre decide el marcado: por ejemplo, un párrafo con “Hello, nombre”.
Fragmento de tipado y uso en TypeScript:
// ChildtypeChildComponentProps={render:(name:string)=>JSX.Element;};constChildComponent:React.FC<ChildComponentProps>=({ render })=>{const name ='DevCode';return<div>{render(name)}</div>;};// ParentconstParentComponent:React.FC=()=>(<ChildComponent render={(name)=><p>Hello,{name}</p>}/>);
¿Qué aporta el tipado de TypeScript en las props?
Define la forma exacta de la función: parámetros y retorno.
Evita errores en tiempo de desarrollo y facilita el autocompletado.
Mejora la comunicación dentro del equipo al documentar contratos.
¿Cómo aplicar render props para listas con data del padre?
Se crea la lógica en el padre: una función render que recibe un arreglo de strings y retorna nodos de React. El padre mantiene la data en un estado local con useState, y el hijo únicamente la pinta con un map dentro de elementos LI.
¿Cómo tipar las props con TypeScript en padre e hijo?
El padre expone una interfaz con la firma de la función render.
El hijo declara una interfaz con la prop data: string[] y la recorre.
Fragmentos clave:
// ParentinterfaceParentComponentProps{render:(data:string[])=>React.ReactNode;}constParentComponent:React.FC<ParentComponentProps>=({ render })=>{const[data]=React.useState<string[]>(/* array de strings */);return<ul>{render(data)}</ul>;};// ChildinterfaceChildComponentProps{ data:string[];}constChildComponent:React.FC<ChildComponentProps>=({ data })=>(<>{data.map((item, index)=>(<li key={index}>{item}</li>))}</>);
¿Qué sucede al integrar el parent component en la UI?
Se importa el parent component y el child component en la vista.
Se pasa la función render del padre que delega el renderizado al hijo.
Resultado: el padre controla la lógica y el hijo se encarga del pintado de la lista dentro de un UL.
Preparación del entorno: clonar el repositorio, ejecutar npm install, luego npm run dev y abrir el localhost.
¿Cuáles son ventajas, desventajas y relación con composition?
El patrón render props convive muy bien con composition: construir interfaces complejas desde componentes pequeños que se combinan. En los ejemplos, el padre define la estructura y el hijo se especializa en pintar datos.
Ventajas.
Reutilización de lógica sin duplicar componentes.
Mantenibilidad y flexibilidad al separar responsabilidades.
Tipado con TypeScript que reduce errores.
Desventajas.
Riesgo de prop drilling si la función o datos viajan por múltiples niveles.
Curva de aprendizaje más exigente para personas nuevas en React.
Habilidades y keywords trabajadas.
Definir interfaces y types de props en TypeScript.
Usar React.FC con genéricos para tipar componentes.
Implementar funciones render que retornan JSX.Element o ReactNode.
Mapear arreglos a elementos LI con key estable.
Aplicar composition para escalar la UI.
¿Qué casos de uso ves para aplicar el patrón de render props en tus componentes? Comparte tus ideas y dudas en los comentarios.
Render Props y Composición en React: Ventajas y Desventajas
Aunque pueda ser una solución rápida y sencilla, utilizar el índice como clave para renderizar componentes puede llevar a problemas de rendimiento y comportamientos inesperados en tu aplicación. Al renderizar listas de elementos, React necesita una forma de identificar de manera única cada elemento para realizar un seguimiento de los cambios y optimizar el DOM. El índice puede cambiar si agregas o eliminas elementos, lo que confunde a React y puede provocar re-renderizados innecesarios o pérdida de estado. Cuando React no puede identificar de manera precisa qué elementos han cambiado, puede terminar re-renderizando toda la lista, incluso si solo un elemento ha sido modificado. Esto afecta negativamente el rendimiento de tu aplicación.
Alternativas
ID único: Si tus datos tienen un ID único asignado (por ejemplo, de una base de datos), úsalo como clave.
Librerías para generar UUIDs: Puedes utilizar librerías como uuid para generar identificadores únicos universales (UUIDs) y usarlos como claves.
Gracias, Juan ! Es completamente cierto, especialmente por el tema de "borrado" y actualización constante del DOM pero, como en este caso no debíamos eliminar elementos, se usó key=index sin problema ✨
excelente tip
Un buen ejemplo de aplicación para este patrón de composición es la creación de modales. En este caso el modal sería nuestro componente hijo, donde viven las funciones que lo abren y lo cierran, y el componente padre donde lo usemos, será el que decida qué se renderizará en el modal. Podría tener una estructura como la siguiente:
Muy buen ejemplo, me gusta este patrón para los modales. Normalmente yo venia haciendo los modales definiendo un nuevo componente para cada uno y pasandolo como child dentro de un <ModalWrapper>
Es parecido el patrón pero este con render props me parece más limpio
Excelente ejemplo de uso Johnatan, empezare a usarlo. Gracias
Un React.Node es un tipo más amplio que representa cualquier cosa que React pueda renderizar, incluyendo elementos, cadenas, números, fragmentos, arrays o null. Por otro lado, un JSX.Element es un tipo específico que representa un elemento de JSX, que se traduce a un objeto de React. En resumen, todos los JSX.Element son React.Node, pero no todos los React.Node son JSX.Element.
Por qué en el primer ejemplo usaste un type en lugar de una interface?
Tal vez porqué es algo pequeño aunque en general es cuestión de gustos. A no se que quieras usar extend ahí si se recomienda usar interface para heredar.
puede ser porque para el uso de una interfaz es como hacer la representacion de un objeto, por ejemplo una instancia, un objeto, o la respuesta de una peticion http y el type puede ser para indicar que tendremos un tipo que puede ser una cosa o otra cosa o otra cosa
Me parece super interesante el patrón de "render props" para darles un poco de formato a los componentes, en realidad hasta ahora estoy aprendiendo mas o menos sobre typescript por lo que al principio me costo entender que estabas haciendo pero lo pensé un poquito y las cosas cobraron sentido, si me preocupa un poco el prop drilling pero me sigue pareciendo un patrón interesante para probar. 😊
Importante destacar que aunque sea con propósito educativo. El index no se puede utilizar como key para ningún componente. Así lo indica React en su documentación oficial. Así que cuidado comunidad, eso causa errores difíciles de depurar.
La manera correcta es usar valores únicos de la data que estamos iterando y como alternativa generar una key random de forma manual o usar un paquete como UUID
Siempre tuve esa duda sobre si era necesario tener que descargar una libreria solo para asignar el key. De ahora en adelante lo haré así
Las render props son una técnica en React que permite compartir código entre componentes a través de funciones como props. Se utilizan para crear componentes más flexibles y reutilizables.
Se emplean en situaciones donde un componente padre necesita controlar cómo se renderiza un componente hijo, permitiendo al padre decidir la lógica de renderizado mientras delega la estructura en el hijo. Son útiles en casos de manejo de estado complejo y en componentes de presentación que requieren personalización en su visualización.
Me volo la cabeza con este patrón. Me encanta, espero poder aplicarlo en mis futuros proyectos. Gracias
Excelente, Fernando !!! 🩵
Me gustó la clase y practiqué un poco con chat GPT y al fin entiendo mejor las render props.
Tengo un par de feedbacks sobre la forma de explicarlo.
1. Usar casos reales para los ejemplos. En la clase aprendimos la forma de implementar el patrón y se mencionaron ventajas y desventajas, pero creo que el aprendizaje es más efectivo si se propone un caso real de uso de este patrón, así no solo entendemos la estructura sino también como usarla para resolver problemas
2. Entendí mejor cuando al buscar en casos reales comprendí cuál es la principal ventaja de usar este patrón de renderizado y es reusar una logica y mostrar la data de forma más flexible. Haría más enfasis en ese tema de que se entienda muy bien la razón de ser de este patrón de renderizado
Los Render Props son útiles en situaciones donde necesitas compartir lógica entre componentes sin duplicar código. Ejemplos reales incluyen:
Componentes de Formulario: Puedes tener un componente de formulario que maneje el estado y la validación, y pasar una función render para definir cómo se ve el formulario.
Listas Dinámicas: Un componente que obtiene datos de una API puede usar render props para permitir que diferentes componentes hijos definan cómo se muestran esos datos (ej. listas, tablas).
Autenticación: Un componente de autenticación puede manejar el proceso de login y permitir que otros componentes definan qué mostrar según si el usuario está autenticado o no.
Estos casos ilustran cómo Render Props fomentan la reutilización y la separación de responsabilidades en React.
Me gusto la clase, y me gustaría añadir las diferencias puntuales entre Render Props y Composition:
En Render Props se pasa una función para controlar el renderizado del componente.
En Composition, se suele utilizar un children, o bien, otros componentes adicionales para construir interfaces más complejas.
Hola, al instalar la dependencias (npm install) me aparece lo siguiente: 2 vulnerabilities (1 low, 1 high) To address all issues, run: npm audit fix Run npm audit for details.
es normal, los paquetes suelen necesitar una actualización ya que estas mejoran la seguridad!
Hay que tener cuidado con upgradearlas porque es posible que dejen de ser compatibles entre ellas o ya no sean retrocompatibles con los metodos que usas en la versión actual que tienes!
Render Props y Composition son dos patrones en React que permiten la reutilización de componentes.
Render Props: Este patrón permite a un componente recibir una función como prop, que se utiliza para renderizar contenido. Favorece la lógica compartida entre componentes, pero puede llevar a problemas de "prop drilling" si se abusa.
Composition: Consiste en combinar componentes pequeños para formar componentes más complejos. Fomenta la creación de interfaces robustas y es más intuitivo para los nuevos desarrolladores.
Ambos enfoques tienen sus ventajas, y la elección depende del caso de uso específico.
que buena la clase, me gusta el flow constante con que se dicta
📚 Render Props en React
🧠 ¿Qué es Render Props?
Render Props es un patrón en React donde un componente recibe una función como prop y esa función devuelve JSX que el componente renderiza.
La idea principal es separar la lógica de la presentación:
Un componente maneja datos o lógica
Otro componente decide cómo se muestran esos datos
En forma simple:
ComponenteA → provee datos o lógica
ComponenteB → decide cómo renderizar la UI
La prop normalmente se llama:
render
children
component
pero lo más común es render.
🧩 Ejemplo 1: Render Props básico
Código
interfaceChildComponentProps{render:(name: string)=>JSX.Element;}exportconstChildComponent=({ render }:ChildComponentProps)=>{const name ="harold";return<div>{render(name)}</div>;};exportconstParentComponent=()=>{return<ChildComponent render={(name)=><p>Hello,{name}</p>}/>;};
🔎 Qué está pasando
1️⃣ ChildComponent
Este componente no decide qué renderizar.
Solo tiene un dato (name) y ejecuta la función que recibe.
const name ="harold";return<div>{render(name)}</div>;
Aquí ocurre algo importante:
render(name)
Esto ejecuta la función que el padre le pasó.
2️⃣ ParentComponent
El componente padre pasa una función como prop:
render={(name)=><p>Hello,{name}</p>}
Esto significa:
Cuando tengas el name
→ usa esta función para renderizarlo
🔄 Flujo del ejemplo
ParentComponent │
│ pasa función render
▼
ChildComponent │
│ tiene el dato:"harold" ▼
render("harold") │
▼
<p>Hello, harold</p> │
▼
<div><p>Hello, harold</p></div>
🧩 Ejemplo 2: Render Props con estado
Este ejemplo es más realista porque un componente maneja el estado y otro renderiza la UI.
Aquí data pasa por varios niveles antes de llegar al componente final.
🧠 Nota importante
El patrón Render Props fue muy popular antes de React Hooks (2019).
Hoy muchos casos se resuelven mejor con Custom Hooks, que hacen el código más simple.
Ejemplo moderno:
const data =useData();
en lugar de:
<DataProvider render={(data)=>...}/>
¡Hola Gustavo! Entiendo tu preocupación por mantener un código limpio y seguir buenas prácticas en React.
La clase "Render Props y Composición en React: Ventajas y Desventajas" explica que el patrón Render Props permite reutilizar lógica entre componentes pasándola como una función. Si bien es una técnica poderosa para la flexibilidad, la clase también menciona que puede fomentar el "prop drilling" y tener una curva de aprendizaje más pronunciada.
Para trabajar con buenas prácticas y evitar código desordenado, es útil explorar patrones como la composición de componentes y, si aplica, considerar otras estrategias de manejo de estado o comunicación entre componentes que se discuten en otras clases.
el useState en ParentComponent era necesario?
No. Puedes simplemente hacer algo como
const data: string[] = ["one", "two", "three"];
Y te va a funcionar igual.
Su mayor fortaleza hoy en día es la Inversión de Control del Renderizado (dejar que el padre decida cómo se ve algo que el hijo procesa), si la finalidad es obtener un dato puro (como window.innerWidth) sin atarlo a ninguna representación visual específica, el Custom Hook es la herramienta más virtuosa por su simplicidad y bajo acoplamiento.
Me parece muy básico, a su vez, creo que render props nos ayuda a pasar fácilmente información entre componentes mientras no sea tan complejo, para evitar dolores de cabeza con el prop drilling.