typescriptadvanced

Compound Component Pattern

Build flexible compound components using React Context for implicit parent-child communication.

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

interface AccordionContext {
  openId: string | null;
  toggle: (id: string) => void;
}

const Ctx = createContext<AccordionContext | null>(null);
const useAccordion = () => {
  const ctx = useContext(Ctx);
  if (!ctx) throw new Error('Must be used within Accordion');
  return ctx;
};

export function Accordion({ children }: { children: ReactNode }) {
  const [openId, setOpenId] = useState<string | null>(null);
  const toggle = (id: string) => setOpenId((prev) => (prev === id ? null : id));
  return <Ctx.Provider value={{ openId, toggle }}>{children}</Ctx.Provider>;
}

Accordion.Item = function Item({ id, title, children }: { id: string; title: string; children: ReactNode }) {
  const { openId, toggle } = useAccordion();
  return (
    <div>
      <button onClick={() => toggle(id)}>{title}</button>
      {openId === id && <div>{children}</div>}
    </div>
  );
};

Use Cases

  • Accordion components
  • Tab interfaces
  • Dropdown menus

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.