šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Component Composition Patterns: A Decision Framework

A decision framework for choosing between plain composition, Compound Components, Render Props, custom hooks, and HOCs.

⚔ Total XP: 0|šŸ’» react XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Decision framework.

Quick Quiz //

What should you try before reaching for any advanced composition pattern?


šŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
šŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Compound Components, Render Props, and Higher Order Components each solve real problems — but knowing which one fits a given situation matters more than knowing all of them exist. This lesson is a practical decision framework for choosing between them, plus custom hooks, based on the actual shape of the problem.

1You Now Have a Whole Toolbox — Which Tool Do You Reach For?

Compound Components, controlled/uncontrolled design, Render Props, and Higher Order Components each solve real, distinct problems. Effective component design isn't about favoring one pattern universally — it's about matching the right tool to the specific shape of the problem at hand.

2Rule of Thumb #1: Default to Plain Composition

Before reaching for any advanced pattern, check whether a component accepting children or a named JSX prop already solves the problem. Most component design needs don't require Context, render props, or a HOC — advanced patterns should be reserved for when plain composition genuinely falls short.

3Rule of Thumb #2: Multiple Cooperating Pieces? Compound Components.

When a component naturally has several visually distinct, state-sharing pieces — like a Tabs list and its panels — Compound Components fits well, letting the consumer arrange those pieces freely while shared state coordination happens invisibly through Context.

4Rule of Thumb #3: Data Logic → Custom Hook. JSX Structure → Render Prop.

For sharing pure data or behavior, a custom hook is simpler and avoids extra nesting. For sharing structural rendering logic the consumer needs to customize per use case — like a list's per-item markup — a render prop remains the better fit, since a hook's return value can't express JSX structure decisions.

5Rule of Thumb #4: Uniform Behavior Across Many Components? Hook First, HOC When Needed.

For cross-cutting concerns applied across many unrelated components, a custom hook called explicitly usually avoids the nested wrapper hell HOCs are prone to. HOCs still make sense in specific cases, like needing to support class components or inject props a consumer can't easily read from a hook.

6Step-by-Step Breakdown

You Now Have a Whole Toolbox — Which Tool Do You Reach For?. You've learned Compound Components, Controlled/Uncontrolled design, Render Props, and Higher Order Components. Real component design isn't about picking a favorite pattern — it's about matching the right tool to the specific problem in front of you. This lesson is a decision framework for exactly that.

Rule of Thumb #1: Default to Plain Composition. Before reaching for any advanced pattern, ask: can this just be solved with children or a named JSX prop? Most component design problems don't need Context, render props, or a HOC — they need a component that accepts and renders whatever JSX it's given. Advanced patterns are for when plain composition genuinely isn't enough.

Rule of Thumb #2: Multiple Cooperating Pieces? Compound Components.. If your component naturally has several visually distinct pieces that need to share state — a Select's trigger and options, a Tabs list and its panels — Compound Components is the right fit, because it lets the consumer arrange those pieces freely while state coordination happens invisibly.

You're designing a Tabs widget with a tab list and separate panel content that need to stay in sync. Which pattern fits best?

  • →Compound Components — multiple cooperating pieces sharing state
  • →A Higher Order Component

Rule of Thumb #3: Reusable Data Logic? Custom Hook. Reusable JSX Structure? Render Prop.. If you're sharing pure data or behavior (fetching, tracking a value), write a custom hook — it's simpler and avoids nesting. If you're sharing structural rendering logic that the consumer must customize per use (like a list's item markup), a render prop is still the better fit, since a hook can't hand back JSX decisions.

Rule of Thumb #4: Uniform Behavior Across Many Unrelated Components? HOC or Hook.. For cross-cutting concerns like authentication checks applied to many different pages, either a HOC or a custom hook can work — but a hook called inside each component, or combined with a layout/route wrapper, usually avoids the wrapper-hell nesting HOCs are prone to. Reach for a HOC mainly when you need to inject props a consumer can't easily read from a hook, like wrapping class components.

For most modern React codebases, what's typically the simpler default for applying an auth check across many pages?

  • →A custom hook called explicitly in each component
  • →Always a Higher Order Component, regardless of context

Mastery Achieved. You now have a practical decision framework: default to plain composition with children; reach for Compound Components when several pieces need to share state; use a custom hook for pure data, a render prop for consumer-controlled markup; and prefer hooks over HOCs for most cross-cutting concerns today. Next, you'll learn the Slot Pattern for even more explicit, named composition points.

Level Up šŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

These are component API design decisions, not browser features.

FirefoxSupported

Fully applicable.

SafariSupported

Fully applicable.

EdgeSupported

Fully applicable.

Accessibility (A11y)

1Pattern Choice Should Never Compromise Semantic Structure

Whichever pattern is chosen, verify the resulting rendered output still produces correct, accessible markup — the composition pattern is an implementation detail, but its rendered result is what assistive technology actually interacts with.

SEO Implications

  • 1

    Simpler Composition Patterns Are Easier to Keep Server-Rendering-Friendly

    Plain composition and compound components generally integrate more cleanly with Server/Client Component boundaries than deeply nested HOCs, since there's less indirection obscuring which parts of the tree need client interactivity.

Best Practices

Revisit Pattern Choices as Requirements Change

A component that started as a simple uncontrolled widget might later need Compound Components or controlled state as new requirements (like cross-component coordination) emerge — don't over-engineer upfront, but be ready to refactor toward a more capable pattern when genuinely needed.

Document Why a Non-Obvious Pattern Was Chosen

If a component uses a HOC or render prop instead of the now-more-common hook approach, a short comment explaining why (e.g. 'needs to support class component consumers') saves future maintainers from wondering if it's just outdated code.

Frequent Bugs

THE BUG

A component was built with Compound Components and Context for a case that only ever has one consumer with no shared-state needs.

THE FIX

This is likely over-engineering — a simpler component accepting children or a couple of named props would solve the same problem with far less implementation complexity. Reserve Compound Components for genuine multi-piece, state-sharing scenarios.

THE BUG

A team keeps writing new Higher Order Components for logic that's really just shared data-fetching.

THE FIX

Pure data/behavior sharing is almost always better served by a custom hook today, avoiding HOC wrapper nesting entirely. Reserve HOCs for cases with a specific reason to prefer them, like class component support.

Real-World Examples

Choosing Between Patterns for a Data Table Feature

A team building a data table needed: (1) sortable column headers sharing sort state — solved with Compound Components; (2) reusable fetching/pagination logic — solved with a custom hook, useTableData; and (3) fully customizable cell rendering per column — solved with a renderCell render prop. Using the right pattern for each sub-problem kept the implementation clear instead of forcing one pattern to do everything.

function DataTable({ columns, data }) {
  const { rows, sortBy, setSortBy } = useTableData(data);
  return (
    <Table>
      <Table.Header columns={columns} sortBy={sortBy} onSort={setSortBy} />
      <Table.Body rows={rows} renderCell={(row, col) => col.renderCell(row)} />
    </Table>
  );
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Reaching for Compound Components and Context for a component with no genuine shared-state need

// Overkill for a single-piece component function Card({ children }) { return <div className="card">{children}</div>; } // this alone is often enough

The Solution //

If a component only has one consumer piece and no cross-piece coordination requirement, plain composition with children is simpler and sufficient. Reserve Compound Components for cases with real multi-piece state sharing.

The Error //

Writing a new Higher Order Component for logic that's purely data-fetching, with no class-component requirement

// Prefer this function useTableData(source) { /* fetching, pagination logic */ } // Over this, unless class components are involved function withTableData(Component) { /* ... */ }

The Solution //

For pure data or behavior sharing with only function-component consumers, a custom hook avoids the wrapper nesting a HOC introduces, and is generally the simpler, more modern default.

Lesson Glossary

[01]Plain Composition

Solving a component design problem with just children or named JSX props, no advanced pattern.

Code Preview
<Card>{children}</Card>

[02]Decision Framework

A practical set of rules for choosing which composition pattern fits a given problem's shape.

Code Preview
Data → hook. Structure → render prop.

[03]Pattern Over-Engineering

Using an advanced pattern (like Compound Components) for a problem simple composition would solve.

Code Preview
Unnecessary complexity

Continue Learning