0Pricing
Frontend Academy · Lección

Componentes compuestos con Context

Comparta estado implícito entre un componente padre y sus hijos designados mediante Context, modelando API como y .

Componentes compuestos con Context es una lección gratuita de Frontend Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Frontend Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Frontend Academy incluye 4 lecciones en total.

¿Qué son los componentes compuestos?

Los componentes compuestos son un conjunto de componentes relacionados diseñados para funcionar juntos como una sola unidad, como <select> y <option> en HTML. El componente padre comparte estado implícito con sus hijos específicos.

El objetivo: API más limpias

En lugar de <Select options={[...]} value={x} onChange={...} />, escriba <Select><Option value="a">Apple</Option></Select>. La estructura es declarativa y nativa de JSX.

Enfoque ingenuo (problema)

Pasar el estado mediante props obliga a quien consume el componente a conectarlo todo. Los hijos no conocen automáticamente el estado del padre.

// Without compound pattern — verbose:
<Tabs activeIndex={0} onChange={setIndex}>
  <TabList>
    <Tab index={0}>Home</Tab>
    <Tab index={1}>Profile</Tab>
  </TabList>
</Tabs>

Context como conexión

El padre crea un Context con el estado compartido y lo proporciona. Los hijos consumen el contexto, sin necesidad de conectar explícitamente las props.

import { createContext, useContext, useState } from 'react';

const TabsContext = createContext(null);

export function Tabs({ children, defaultIndex = 0 }) {
  const [activeIndex, setActiveIndex] = useState(defaultIndex);
  return (
    <TabsContext.Provider value={{ activeIndex, setActiveIndex }}>
      <div className="tabs">{children}</div>
    </TabsContext.Provider>
  );
}

Los componentes hijos consumen

Cada hijo lee el contexto, sin pasar props por los distintos niveles del árbol.

export function Tab({ index, children }) {
  const { activeIndex, setActiveIndex } = useContext(TabsContext);
  const isActive = activeIndex === index;
  return (
    <button
      className={isActive ? 'active' : ''}
      onClick={() => setActiveIndex(index)}
    >
      {children}
    </button>
  );
}

export function Panel({ index, children }) {
  const { activeIndex } = useContext(TabsContext);
  if (activeIndex !== index) return null;
  return <div className="panel">{children}</div>;
}

Propiedades estáticas para facilitar el descubrimiento

Asocie los subcomponentes al padre para que los usuarios los descubran mediante el autocompletado.

Tabs.Tab = Tab;
Tabs.Panel = Panel;

// Usage:
<Tabs>
  <Tabs.Tab index={0}>Home</Tabs.Tab>
  <Tabs.Tab index={1}>Profile</Tabs.Tab>
  <Tabs.Panel index={0}>Home content</Tabs.Panel>
  <Tabs.Panel index={1}>Profile content</Tabs.Panel>
</Tabs>

Ejemplo real: Disclosure

Un widget Disclosure tiene hijos Trigger y Panel que comparten mediante Context un estado abierto/cerrado.

function Disclosure({ children }) {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <DisclosureContext.Provider value={{ isOpen, setIsOpen }}>
      <div>{children}</div>
    </DisclosureContext.Provider>
  );
}

function Trigger({ children }) {
  const { isOpen, setIsOpen } = useContext(DisclosureContext);
  return <button onClick={() => setIsOpen(o => !o)}>{children}</button>;
}

function Panel({ children }) {
  const { isOpen } = useContext(DisclosureContext);
  return isOpen ? <div>{children}</div> : null;
}

Los hooks como API pública

Exporte un hook personalizado para que los usuarios puedan crear sus propios componentes sobre los suyos.

export function useTabs() {
  const ctx = useContext(TabsContext);
  if (!ctx) throw new Error('useTabs must be used inside <Tabs>');
  return ctx;
}

Componentes compuestos polimórficos

Permita que los padres representen cualquier elemento mediante una prop as o el patrón asChild, como hace Radix UI. Así, los componentes compuestos pueden combinarse con JSX arbitrario.

Patrones de componentes compuestos headless

Las bibliotecas headless, como Radix y Headless UI, ofrecen componentes compuestos sin estilos: incorporan la lógica de accesibilidad y permiten aplicar los estilos que necesite.

Problema: inspeccionar los hijos

Un patrón antiguo utilizaba React.Children para inspeccionar los hijos, pero era frágil y propenso a fallos. Prefiera siempre Context para compartir el estado.

Comprobación rápida

En un patrón de componentes compuestos, ¿cómo se comunican los componentes hijos con su padre?

Repaso: componentes compuestos

Los componentes compuestos permiten que varias partes relacionadas funcionen como una unidad declarativa. Use Context para compartir el estado: Provider en el padre y useContext en los hijos. Asocie los subcomponentes como propiedades estáticas para facilitar su descubrimiento. Exporte un hook personalizado como API pública. Radix y Headless UI son excelentes referencias. Prefiera Context a inspeccionar los hijos con Children.

Preguntas frecuentes

¿La lección «Componentes compuestos con Context» es gratis?

Sí — el texto completo de «Componentes compuestos con Context» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Frontend Academy, actualiza a CoddyKit PRO. El curso de Frontend Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Componentes compuestos con Context»?

Comparta estado implícito entre un componente padre y sus hijos designados mediante Context, modelando API como y . Practicas Frontend Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Frontend Academy?

No se requiere experiencia previa. Frontend Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Componentes compuestos con Context»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Frontend Academy?

Sí. Cada lección de Frontend Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Componentes compuestos con Context
  2. Render Props y patrones HOC
  3. Portales para modales y tooltips
  4. Límites de errores
← Volver a Frontend Academy