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>
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



