Busca en todas las páginas de la documentación
// Composición basada en slots: pasa componentes como props
function Layout({ header, sidebar, children }: {
header: React.ReactNode;
sidebar: React.ReactNode;
children: React.ReactNode;
}) {
return (
<div className="grid grid-cols-[240px_1fr] grid-rows-[64px_1fr]">
<header className="col-span-2">{header}</header>
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
);
}
// Uso
<Layout
header={<TopNav user={currentUser} />}
sidebar={<SideMenu items={menuItems} />}
>
<Dashboard data={dashboardData} />
</Layout>Cuándo usarlo: Siempre que necesites un contenedor, diseño o contenedor reutilizable que deba permanecer agnóstico sobre su contenido. Prefiere la composición sobre la herencia en todos los casos en React.
import { type ReactNode } from "react";
// Un componente Card con slots componibles
interface CardProps {
media?: ReactNode;
actions?: ReactNode;
children: ReactNode;
variant?: "elevated" | "outlined";
Lo que esto demuestra:
ReactNode (media, actions, children)Card) dentro de uno específico del dominio (ProductCard)ProductCard no es una subclase de Cardchildren es la primitiva de composición principal — cualquier JSX anidado dentro de un componente se pasa como props.children.ReactNode) te permiten inyectar contenido en posiciones específicas dentro del diseño de un componente.{children} como marcador de posición.| Patrón de prop | Tipo | Propósito |
|---|---|---|
children | ReactNode | Slot predeterminado para contenido anidado |
Slot con nombre (p. ej. header) | ReactNode | Colocación explícita de contenido en un área específica |
| Callback de renderizado | (data: T) => ReactNode | Contenido que necesita acceso al estado interno (véase render-props) |
| Prop de componente | React.ComponentType<P> | Inyectar un componente completo para instanciar internamente |
Patrón de inyección de componentes — pasa un tipo de componente en lugar de un elemento renderizado:
interface ListProps<T> {
items: T[];
renderItem: React.ComponentType<{ item: T }>;
}
function List<T>({ items, renderItem: Item }
Composición de proveedores — aplana los proveedores de contexto anidados:
function AppProviders({ children }: { children: ReactNode }) {
return (
<ThemeProvider>
<AuthProvider>
<QueryProvider>
{children}
</QueryProvider>
</AuthProvider>
ReactNode para slots que aceptan cualquier contenido renderizable (strings, elementos, fragmentos, null).React.ComponentType<P> cuando necesites pasar un componente que será instanciado con props específicas.ReactElement solo cuando necesites limitar a elementos JSX reales (excluyendo strings y números).List<T>) preserva la seguridad de tipos en todo el límite del componente.Sobreuso de children para múltiples slots — Cuando pasas todo como children, pierdes el control sobre la colocación. Solución: Usa props con nombre ReactNode para áreas de contenido distintas.
Prop drilling a través de capas compuestas — La composición profunda puede llevar a pasar props a través de muchos niveles. Solución: Usa contexto para preocupaciones realmente transversales y mantén la composición superficial.
Romper la memoización con slots JSX en línea — Pasar <Component /> en línea como una prop crea una nueva referencia de elemento en cada renderizado. Solución: Eleva el contenido de slot estático fuera del renderizado o envuelve con useMemo para árboles costosos.
Confundir especialización con configuración — Crear un nuevo componente solo para establecer algunas props está bien; crear un contenedor que re-expone todas las props originales es una señal de que necesitas composición, no envolvimiento. Solución: Usa el componente original directamente y pasa props en el sitio de llamada.
| Enfoque | Compensación |
|---|---|
| Composición (slots) | Más flexible; requiere más JSX en el sitio de llamada |
| Props de configuración (strings de variante) | Menos flexible pero API más simple para casos comunes |
| Render props | Más poder cuando el contenido del slot necesita estado interno |
| Componentes de orden superior | Añade comportamiento sin cambiar la API, pero más difícil de depurar |
| Herencia | No recomendado en React — se rompe con componentes de función |
children?ReactNode (como header, sidebar, actions) cuando el contenido necesita colocarse en posiciones específicas dentro de un diseño.children solo cuando hay un único área de contenido.children solo no puede proporcionar.// Elemento renderizado: pasas JSX
<Card media={<img src={url} alt="photo" />} />
// Inyección de componentes: pasas un tipo de componente
<List items={data} renderItem={ProductRow} />function AppProviders({ children }: { children: ReactNode }) {
return (
<ThemeProvider>
<AuthProvider>
<QueryProvider>
{children}
</QueryProvider>
</
ReactNode, ReactElement, y React.ComponentType<P> en TypeScript?ReactNode acepta cualquier contenido renderizable: strings, números, elementos, fragmentos y null.ReactElement se limita solo a elementos JSX reales, excluyendo strings y números.React.ComponentType<P> es un tipo de componente (función o clase) que puede instanciarse con props de tipo P.List<T> la seguridad de tipos?interface ListProps<T> {
items: T[];
renderItem: React.ComponentType<{ item: T }>;
}
function List<T>({ items, renderItem:
<Component /> en línea como una prop crea una nueva referencia de elemento React en cada renderizado.React.memo, la nueva referencia causa que se re-renderice.useMemo.ReactNode?(data: T) => ReactNode) cuando el contenido del slot necesita acceso al estado interno del componente padre.ReactNode simple cuando el contenido es independiente del estado interno del componente.ReactNode y actualiza solo cuando sea necesario.children como slots con nombre en TypeScript?interface LayoutProps {
header: ReactNode;
sidebar: ReactNode;
children: ReactNode;
}
function Layout({ header, sidebar, children }: LayoutProps) {
<AppProviders> en el sitio de llamada.T del array items y lo aplica en renderItem.item dentro del componente de renderizado.ReactNode.children es una prop estándar de React que recibe JSX anidado.