liveBook · Manning

Composite design pattern

As explained in React in Depth

The Composite pattern is a structural design pattern that composes individual objects into hierarchical structures while allowing individual objects and compositions to be treated uniformly.

In React, the Composite pattern builds a complex interface from focused subcomponents rather than putting every option and behavior into one component. A radio group, for example, can expose `RadioGroup.Option` and `RadioGroup.Details`: callers assemble the structure in JSX, while the parts coordinate through context. The namespaced API does not make the parts special internally; they remain regular components. section 2.2 section 2.2.3

A radio group shows how the responsibilities divide:

  • `RadioGroup` owns the selected value and change handler. It provides the input name, selected value, and handler to its children through group context. section 2.2.4
  • `Option` reads that context, renders the radio input, and passes its own selection status through a second context. section 2.2.4
  • `Details` reads the option context and renders its children only when that option is selected. section 2.2.4

Compose an option in JSX

`<RadioGroup name="bread" onChange={onChange("bread")}><RadioGroup.Option value="bagel">Bagel</RadioGroup.Option><RadioGroup.Option value="croissant" isPopular>Croissant</RadioGroup.Option></RadioGroup>` keeps option content and structure in JSX instead of defining options in a JavaScript array. The group handles shared behavior; each option owns its particular content and presentation. section 2.2.3 section 2.2.4

This split becomes useful when a single component grows bloated as features accumulate, or when parts of an interface need to be recombined. It trades a direct parent–child implementation for more abstraction and context wiring. Use it where that flexibility earns its keep, not merely to rename a simple component’s children. section 2.2 section 2.2.5

Listing 2.12 The Option component
import { useContext } from "react";
import { RadioGroupContext, RadioOptionContext } from "./contexts";
export function Option(
  { value, icon, isPopular, children }     #1
) {
  const { name, selectedValue, onChange } =     #2
    useContext(RadioGroupContext);    #2
  const isSelected = selectedValue === value;
  return (
    <label style={isPopular ? { border: "1px dashed red" } : null}>
      {icon}
      <input
        type="radio"
        value={value}
        name={name}
        checked={isSelected}
        onChange={() => onChange(value)}
      />
      <RadioOptionContext.Provider value={isSelected}>   #3
        {children}    #3
      </RadioOptionContext.Provider>    #3
      {isPopular ? <strong>figure Popular!</strong> : null}
    </label>
  );
}

The `Option` implementation shows both sides of the composition: it consumes group context for shared radio behavior and provides option context to its children. section 2.2.4

How React in Depth covers it

How deep it goes
Works through a radio group's JSX, state, props, and two contexts down to individual component implementations.
Examples
Uses a breakfast-ordering radio group with meal and bread options, popular-option styling, and selection-dependent details.
What it assumes
Assumes working knowledge of React components, JSX, state hooks, and context rather than introducing those APIs from zero.
What you can do after
Build it from scratch as a radio group whose subcomponents share behavior through contexts while retaining focused responsibilities.
How it connects
Connects component composition with React Context, state management, and the Provider pattern.

Also explained in

Compare how 4 books explain composite design pattern →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of React in Depth. The section links point to the parts of the book it draws on.