React
/Advanced
Compound Components Pattern
Definition
A design pattern where multiple components work together to share state and logic implicitly, allowing the developer to declaratively assemble the UI without passing dozens of props.
Explain Like I'm New
Think of the standard HTML `<select>` and `<option>` tags. They are separate tags, but they magically communicate. When you click an `<option>`, the `<select>` knows about it. The Compound Components pattern allows you to build your own React components that work exactly like this.
Real World Example
Building a `<Tabs>` component. Instead of passing an array of objects to `<Tabs data={myTabs} />`, you use Compound Components: `<Tabs><TabList><Tab>Profile</Tab></TabList><TabPanels><Panel>Profile Data</Panel></TabPanels></Tabs>`.
Common Use Cases
- •Building highly flexible UI libraries (like Headless UI or Radix)
- •Avoiding 'Prop explosion' (components that take 20 different props to configure layout)
Interactive Example
import React, { useState, createContext, useContext } from 'react'; // 1. Create a Context for the compound components to share const ToggleContext = createContext(); // 2. The Parent Component manages the state export function Toggle({ children }) { const [on, setOn] = useState(false); return ( <ToggleContext.Provider value={{ on, setOn }}> <div className='p-4 border rounded bg-gray-50'>{children}</div> </ToggleContext.Provider> ); } // 3. Child components consume the context export function ToggleOn({ children }) { const { on } = useContext(ToggleContext); return on ? children : null; } export function ToggleOff({ children }) { const { on } = useContext(ToggleContext); return on ? null : children; } export function ToggleButton() { const { on, setOn } = useContext(ToggleContext); return <button onClick={() => setOn(!on)} className='bg-blue-500 text-white p-2 rounded'>Toggle</button>; } // 4. Usage: Highly declarative and flexible! export default function App() { return ( <Toggle> <ToggleButton /> <hr className='my-2'/> <ToggleOn>The button is ON!</ToggleOn> <ToggleOff>The button is OFF!</ToggleOff> </Toggle> ); }
Interview Questions
basic
- What is a Compound Component?
- Why not just pass a big configuration object as a prop?
intermediate
- How do the parent and child components communicate in this pattern?
- How do you restrict children to only be specific components?
advanced
- What is the difference between using `React.Children.map` and using Context for this pattern?
- How does this pattern improve flexibility?