Sikau

React patterns at scale · Day 1 · about 35 min

Compound components

Parts that share hidden state through context.

The prop that ate the component

Every large React codebase has one: an <Accordion> that started with an items array and grew a prop for every request. headerIcon, renderPanelFooter, disabledIds, openOnHover, wrapHeaderInH3… Each new screen needs something slightly different, and each prop makes the component harder to read, test and change. Addy Osmani's field guide calls this kind of growth accidental complexity — complexity that comes from how we built something, not from the problem itself.

The fix that design systems like Reach UI, Radix and Headless UI reached for is the compound component: instead of one component configured by props, you get a family of small parts that you arrange yourself, exactly like <select> and <option> in HTML. This course starts there, because the patterns that make a component reusable at scale are mostly about who gets to decide what.

Parts that talk through context

The parent owns the state (which item is open) and shares it through context. Each part reads what it needs. The person using the accordion never sees the state — they just arrange the parts, wrap them in headings, add icons or reorder them. That is inversion of control: the component handles behaviour, the user controls the markup.

const AccordionContext = createContext(null);

function Accordion({ defaultOpen = null, children }) {
  const [openId, setOpenId] = useState(defaultOpen);
  const toggle = (id) => setOpenId((cur) => (cur === id ? null : id));
  return (
    <AccordionContext.Provider value={{ openId, toggle }}>
      {children}
    </AccordionContext.Provider>
  );
}

Accordion.Item = Item;
Accordion.Header = Header;
Accordion.Panel = Panel;

A thali plate: The plate decides that each bowl gets one portion and nothing spills. What goes in the bowls, and where they sit on the plate, is up to the cook. The accordion is the plate; headers and panels are the bowls.

The rest of this lesson

  • Why not cloneElement?explain
  • Wrapped in a headingpredict
  • Who decides whatmatch
  • Building a compound componentorder
  • Build a compound accordionwrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 10 lessons of React patterns at scale