Hijos y composición
El HTML siempre ha funcionado por anidamiento: un <select> envuelve sus <option>, un <ul> envuelve sus <li>, un <button> envuelve su etiqueta. El elemento del medio es hijo del elemento que lo rodea, y ambos trabajan juntos para formar lo que ves. Los componentes de React pueden funcionar de la misma manera. En lugar de pasar todo mediante props con nombre, un componente puede envolver contenido igual que hacen los elementos nativos, y esa sola idea es lo que separa a un componente que configuras de un componente que compones.
Este capítulo construye el argumento de la misma forma en que lo hace el curso, a través de un Button para una librería de componentes: primero los children, después el spreading de props, y por último los detalles que hacen que un componente sea reutilizable en la práctica.
Children como interfaz
El capítulo de Props presentó children: el contenido entre la etiqueta de apertura y cierre de un componente llega como una prop con ese nombre. Lo que esto te da para la reutilización es más grande de lo que parece.
function Button({ children }) {
return <button>{children}</button>
}
// uso: <Button>Comprar ahora</Button>El componente decide dónde se renderizan los children, y quien lo usa decide qué son. Compara eso con una prop text, que funciona bien hasta que quien la usa quiere algo más que un string. Con children, no hay nada que impida pasar más que solo texto:
// uso:
// <Button>
// <CartIcon />
// Comprar ahora
// </Button>Un ícono a la izquierda de la etiqueta, sin una prop icon, sin una opción iconPosition="left", sin que quien escribió el componente haya tenido que anticipar nada. ¿Quieres el ícono a la derecha? Muévelo al otro lado del texto. Cada prop de configuración que el autor habría tenido que inventar se disuelve en el hecho de que quien llama al componente simplemente escribe el markup que tenía en mente.
Reenviando el resto de las props
Un Button que renderiza un <button> nativo tiene un segundo problema: los eventos. Cuando quien lo usa escribe <Button onClick={...}>, ese onClick llega como una prop personalizada a tu componente; no pasa nada a menos que el componente lo reenvíe al <button> real que hay debajo. Podrías reenviar onClick a mano, luego onDoubleClick, luego style, luego className, y aun así nunca cubrirías todo lo que un botón nativo acepta. La sintaxis de spread los reenvía todos de una sola vez:
function Button({ children, ...rest }) {
return <button {...rest}>{children}</button>
}Desestructura las props que tu componente realmente maneja, junta todo lo demás con la sintaxis rest, y esparce (spread) el resto sobre el elemento subyacente. Cada atributo válido de botón que pase quien lo usa, incluidos los manejadores de eventos, termina donde corresponde. Las props que tu componente inventa por su cuenta (digamos, un variant) se desestructuran aparte para que nunca lleguen al elemento del DOM.
Haciendo espacio para tu propia API
Los componentes reutilizables suelen agregar opciones por encima del elemento nativo. El botón del curso recibe un size ("sm" o "lg") y un variant ("success", "warning", "danger"), cada uno mapeado a una clase CSS:
function Button({ children, size, variant, className, ...rest }) {
const sizeClass = size ? `button-${size}` : ''
const variantClass = variant ? `button-${variant}` : ''
const allClasses = [sizeClass, variantClass, className].filter(Boolean).join(' ')
return (
<button className={allClasses} {...rest}>
{children}
</button>
)
}Esa fusión evita un bug sutil. Si el componente define className y quien lo usa también pasa uno, el que llegue de último al elemento es el que gana: si esparces el resto después de tu propio className, la clase de quien llama sobrescribe la tuya en silencio; si lo esparces antes, la tuya sobrescribe la de ellos. La solución es desestructurar className aparte y fusionar los strings tú mismo. Librerías como clsx o classnames existen justamente para hacer esta fusión una vez que las condiciones se multiplican.
children no necesita una prop de texto, una prop de ícono y una prop de posición del ícono. Quien lo usa escribe el ícono y el texto dentro de las etiquetas en el orden que quiera, y el Button coloca ese contenido donde corresponde. El anidamiento, lo que el HTML siempre ha hecho, es también el mejor truco de React para la reutilización.
A continuación: Componentes compuestos, donde un componente se convierte en varios que trabajan juntos.

