Frontend Master

JavaScript Curriculum

Component Composition
+60 XP

Component Composition

medium
~30 min·60 XP

The coffee shop app has cards, modals, and page layouts that look different but share the same shell. Composition lets you write the shell once and slot in different content — without copying JSX.

Component Composition

React's answer to code reuse is composition — not inheritance. Components wrap other components, slot content as props, and share state through Context. This produces flexible UIs with clear boundaries.

The children Prop — Four Patterns

From basic wrappers to named slots and render props:

children-prop.jsx

Everything between opening and closing tags becomes the children prop. The wrapper renders it wherever {children} appears.

Component definition
function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  )
}
Usage
<Card>
  <h3>Espresso</h3>
  <p>Rich and concentrated</p>
  <button>Order</button>
</Card>
ℹ️children is just a prop
React automatically sets the `children` prop to whatever JSX is between a component's opening and closing tags. You can also pass it explicitly: `<Card children={<p>text</p>} />` — but the tag syntax is much cleaner.

Composition Patterns — Three Architecture Approaches

Specialisation, compound components, and container/presenter:

composition-patterns.jsx

A specific component wraps a generic one and passes fixed props. Avoids repetition while keeping the generic version flexible.

// Generic — accepts any props
function Button({ variant, size, children, ...rest }) {
  return (
    <button className={`btn btn-${variant} btn-${size}`} {...rest}>
      {children}
    </button>
  )
}

// Specialised — pre-configured
function PrimaryButton(props) {
  return <Button variant="primary" size="md" {...props} />
}

function DangerButton(props) {
  return <Button variant="danger" size="sm" {...props} />
}

// Usage:
<PrimaryButton onClick={order}>Order now</PrimaryButton>
<DangerButton onClick={cancel}>Cancel</DangerButton>
💡Favour composition over inheritance
React's official recommendation is to never use class inheritance to build component trees. If you need to share logic between components, extract it to a custom hook. If you need to share UI structure, use composition.

Named Slot Builder — Live Composer

Toggle slots on/off to see how the component and JSX change:

slot-builder.jsx
Slots & props
accent color
Today's Special
⭐ Featured

Rich oat milk cappuccino with house-made syrup

£3.50

Generated JSX
<Card
  header={<h3>Today's Special</h3>}
  badge={true && <span className="badge">Featured</span>}
  footer={true && (
    <button className="order-btn">Add to cart</button>
  )}
  accentColor="#1f6feb"
>
  <p>Rich oat milk cappuccino with house-made syrup</p>
  <p className="price">£3.50</p>
</Card>
⚠️Slots vs children
Use `children` when the content is a single block. Use named props (header, footer, sidebar) when you need to render multiple independent sections. Named props give callers precise control over each region.

Your Challenge

Build a Card component that accepts header, children, footer, and badge as props — render each only if provided. Create MenuCard, OrderCard, and ProfileCard by passing different content to the same Card. Show how three different UIs come from one shell component.

Challenge

Build a Card component that accepts header, children, footer, and badge as props (named slots). Create three specialisations: MenuCard, OrderCard, ProfileCard — each passes different content to the same Card shell.

children-propnamed-slotscompound-componentscompositionrender-propspecialisationcontainer-presenterlayout-componentsContext
Component Composition | Nexus Learn