JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

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

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsreactAdvanced Patterns
PrevNext
react
advanced
15 min read

Advanced Patterns

compound-components
custom-hooks
higher-order-components
hoc
patterns
render-props
reusability

React patterns evolved from mixins to HOCs to render props to hooks — compound components share implicit state for flexible APIs, while custom hooks have replaced most logic-sharing patterns.

Key Points

1Pattern Evolution

Mixins → HOCs → Render Props → Custom Hooks. Each generation improved composability and simplified logic sharing.

2Higher-Order Components

Functions that wrap components to inject props. Suffer from wrapper hell, prop collisions, and poor TypeScript inference — largely replaced by hooks.

3Render Props

Components that call a function prop to delegate rendering. Still used by headless UI libraries for behavior + rendering separation.

4Custom Hooks

Plain functions that extract reusable stateful logic — compose naturally without wrapper components. The modern default.

5Compound Components

Related components sharing implicit state via Context — the standard pattern for flexible component APIs (tabs, selects, accordions).

What You'll Learn

  • Explain the evolution of React patterns and why hooks replaced HOCs/render props
  • Implement compound components using Context for flexible component APIs
  • Know when to use each pattern in modern React applications

Deep Dive

React has gone through several generations of component design patterns. Understanding this evolution — and when each pattern is still appropriate — demonstrates senior-level React knowledge.

Pattern Evolution

Mixins (deprecated) → Higher-Order Components → Render Props → Custom Hooks. Each generation solved the same problem — sharing stateful logic between components — with increasing simplicity and composability.

Higher-Order Components (HOCs)

A HOC is a function that takes a component and returns a new enhanced component: const EnhancedComponent = withAuth(MyComponent). The HOC wraps the original component, injecting props (auth data, theme, etc.) without modifying the component itself.

Common examples: withRouter (React Router v5), connect() (Redux), withAuth, withTheme.

Problems: wrapper hell (deeply nested component trees), prop collision (two HOCs injecting the same prop name), hard to trace which HOC provides which prop, and TypeScript type inference struggles with HOCs.

Render Props

A render prop is a function prop that a component calls to determine what to render: <Mouse render={({ x, y }) => <Cursor x={x} y={y} />} />. The Mouse component handles the logic (tracking mouse position) and delegates rendering to the consumer via the function.

The children prop can also be a function: <Mouse>{({ x, y }) => <Cursor x={x} y={y} />}</Mouse>. This is the same pattern — the prop name doesn't matter.

Render props are still used by headless UI libraries (Downshift, Headless UI) where the library handles behavior and the consumer controls rendering.

Custom Hooks

Custom hooks extract reusable stateful logic into plain functions: const { x, y } = useMouse(). They solve the same problem as HOCs and render props without wrapper components, prop collisions, or composition complexity.

Hooks compose naturally — a custom hook can call other hooks, and you can use multiple hooks in one component without nesting. This is why hooks replaced most HOC and render prop usage.

Compound Components

Compound components are a set of related components that share implicit state and work together as a unit. The classic example is HTML's <select> and <option> — they communicate implicitly.

In React, compound components use Context to share state:

TSX
<Tabs defaultValue="a">
  <TabList>
    <Tab value="a">Tab A</Tab>
    <Tab value="b">Tab B</Tab>
  </TabList>
  <TabPanels>
    <TabPanel value="a">Content A</TabPanel>
    <TabPanel value="b">Content B</TabPanel>
  </TabPanels>
</Tabs>

The parent (Tabs) manages state, and children (Tab, TabPanel) consume it via Context. This creates a flexible, declarative API where consumers control structure and layout.

Compound components are still the dominant pattern for component libraries (Radix UI, Headless UI, Reach UI) because they give consumers maximum flexibility.

When to Use Each Today

  • Custom hooks: default choice for sharing stateful logic between components
  • Compound components: building flexible component APIs (tabs, accordions, dropdowns, selects)
  • Render props: headless UI libraries, rare cases where the consumer needs to control rendering of internal parts
  • HOCs: legacy codebases, decorating at the module level (rare in modern code)

Key Interview Distinction

Hooks replaced HOCs and render props for logic sharing because they compose without wrapper hell. Compound components remain the standard for flexible component APIs. Understanding the evolution (and why each pattern exists) demonstrates experience with real React codebases across different eras.

Fun Fact

The render props pattern was so popular that Michael Jackson (the developer, not the musician) coined the term and wrote a famous blog post in 2017 titled 'Use a Render Prop!' arguing it was superior to HOCs. Within two years, hooks made the post largely obsolete — Jackson himself acknowledged this and moved on to co-create Remix.

Learn These First

Hooks

intermediate

Context API

intermediate

Continue Learning

Hooks

intermediate

Context API

intermediate

Components

beginner

Practice What You Learned

Build an infinite scroll component in React using Intersection Observer that loads more items as the user scrolls, with loading states and race condition handling.
mid
machine-coding
Infinite scroll uses Intersection Observer to detect when a sentinel element near the bottom of the list enters the viewport, triggering a fetch for the next page of data. A ref-based approach with proper cleanup prevents race conditions and duplicate requests.
Explain common React patterns: Compound Components, Render Props, and Custom Hooks.
senior
patterns
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.
What are Higher-Order Components (HOCs) in React, and why are they less commonly used today?
senior
patterns
A Higher-Order Component is a function that takes a component and returns an enhanced component with additional props or behavior; they're less common now because React Hooks provide a cleaner solution for logic reuse without wrapper components.
How would you design and implement a reusable Pagination component in React?
senior
patterns
A reusable Pagination component manages page state, renders page numbers with ellipsis for large ranges, and exposes both controlled and uncontrolled APIs. It should include keyboard navigation, ARIA attributes for accessibility, and integrate cleanly with server-side pagination endpoints.
Previous
Lists & Keys
Next
Performance Optimization
PrevNext