JS Guide
HomeQuestionsSearchResources
Search

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeQuestionsreact
PrevNext
react
senior
patterns

Explain common React patterns: Compound Components, Render Props, and Custom Hooks.

patterns
compound-components
render-props
custom-hooks
composition
Quick Answer

Compound Components share implicit state between related components (like <select>/<option>). Render Props pass render functions to share code. Custom Hooks extract reusable stateful logic. Today, Custom Hooks are preferred over Render Props for most cases.

Detailed Explanation

Compound Components:

  • Multiple components work together as a unit
  • Share implicit state via Context
  • Flexible, declarative API
  • Examples: Tabs/Tab, Accordion/Panel, Select/Option

Render Props:

  • Component receives function that returns React elements
  • Function receives state/behavior as arguments
  • Enables code reuse without HOCs
  • Largely replaced by hooks

Custom Hooks:

  • Extract stateful logic into reusable functions
  • Can use other hooks
  • Cleaner than render props or HOCs
  • Modern preferred approach

Pattern Evolution:

  • Mixins → HOCs → Render Props → Hooks
  • Hooks solve most use cases more elegantly
  • Compound components remain useful for component APIs

Code Examples

Compound Components pattern
// Context for implicit state sharing
const TabsContext = createContext();

function Tabs({ children, defaultTab }) {
  const [activeTab, setActiveTab] = useState(defaultTab);
  
  return (
    <TabsContext.Provider value={{ activeTab, setActiveTab }}>
      <div className="tabs">{children}</div>
    </TabsContext.Provider>
  );
}

function TabList({ children }) {
  return <div className="tab-list">{children}</div>;
}

function Tab({ id, children }) {
  const { activeTab, setActiveTab } = useContext(TabsContext);
  
  return (
    <button 
      className={activeTab === id ? 'active' : ''}
      onClick={() => setActiveTab(id)}
    >
      {children}
    </button>
  );
}

function TabPanels({ children }) {
  return <div className="tab-panels">{children}</div>;
}

function TabPanel({ id, children }) {
  const { activeTab } = useContext(TabsContext);
  if (activeTab !== id) return null;
  return <div className="tab-panel">{children}</div>;
}

// Usage - clean, declarative API
function App() {
  return (
    <Tabs defaultTab="tab1">
      <TabList>
        <Tab id="tab1">First</Tab>
        <Tab id="tab2">Second</Tab>
      </TabList>
      <TabPanels>
        <TabPanel id="tab1">First content</TabPanel>
        <TabPanel id="tab2">Second content</TabPanel>
      </TabPanels>
    </Tabs>
  );
}

Resources

React Docs - Reusing Logic with Custom Hooks

docs

Kent C. Dodds - Compound Components

article

Related Questions

What are custom hooks and how do you create them?

mid
hooks

What is React Context and when should you use it?

mid
context
Previous
How do Error Boundaries work in React and what are their limitations?
Next
What are Higher-Order Components (HOCs) in React, and why are they less commonly used today?