[ReactJS]

4 Oct 2025

-

2 min read time

Advanced Guide on React Component Composition

Master React component composition with this comprehensive guide: learn “Thinking in React,” core patterns like children, render props, HOCs, and compound components, plus advanced techniques including performance tweaks, server components, dynamic slots, and custom hooks for scalable, maintainable apps.

Kalle Bertell

By Kalle Bertell

Advanced Guide on React Component Composition

Mastering React Component Composition

When you finish this article, you’ll understand how to design React apps from the ground up—starting with “Thinking in React,” moving through core composition patterns (children, render props, HOCs, compound components), and diving into advanced topics like performance tweaks, server components, dynamic slots, configuration trade-offs, and cross-cutting concerns with hooks.

Image

Thinking in React

React’s official guide breaks UI design into five steps. Following them helps you build predictable, maintainable layouts.

  1. Break UI into a component hierarchy

    Sketch your app and identify self-contained pieces.

  2. Build a static version in React

    Render hard-coded data to confirm your component tree.

  3. Identify the minimal (but complete) representation of UI state

    Find every changing value your UI needs.

  4. Identify where your state should live

    Lift state up to the closest common ancestor that needs it.

  5. Add inverse data flow

    Pass event handlers downward so children can update shared state.

Image

React’s official guide on Thinking in React provides a detailed walkthrough.

Core Composition Patterns

Component composition replaces inheritance with simple functions and props, making your UI more modular.

1. Children Prop

Pass nested JSX directly into a component.

<Modal>
  <h2>Title</h2>
  <p>Content goes here.</p>
</Modal>

2. Render Props

Provide a function as a prop to share state or behavior.

<DataFetcher render={data => <List items={data} />} />

3. Higher-Order Components (HOCs)

Wrap a component to inject additional props or logic.

const withAuth = Wrapped => props => (
  isAuthenticated ? <Wrapped {...props} /> : <Redirect to="/login" />
);

Benefits

  • Reusability

  • Readability

  • Testability

Anti-patterns to avoid

  • Deep nesting of HOCs

  • Tight coupling between wrapper and wrapped components

Learn more in Robin Wieruch’s guide on React component composition .

Pattern

Description

Code Example

Pros

Cons

Children Prop

Pass JSX as children to a component

`<Modal><p>Content</p></Modal>`

Simple, flexible

Limited to layout composition

Render Props

Use a function prop to share state or behavior

`<DataFetcher render={data => <List items={data} />} />`

Dynamic, decouples state

Verbose, can cause prop drilling

Higher-Order Components

Wrap components to add props/logic

`withAuth(WrappedComponent)`

Code reuse, logic separation

Can lead to deep nesting

Compound Components

Compound components let you share implicit state without polluting global context.

  • Definition: A parent component manages state and syncs data across its children.

  • Implementation: Use `React.Children` and `React.cloneElement` to pass props.

  • Example:

    function Tabs({ children }) {
      const [active, setActive] = useState(0);
    
      return (
        <div>
          {React.Children.map(children, (child, i) =>
            React.cloneElement(child, {
              isActive: i === active,
              onSelect: () => setActive(i)
            })
          )}
        </div>
      );
    }
  • Use cases: Tab lists, Accordions, Toggle groups

  • Limitations: Not ideal if children aren’t direct descendants

Detailed walkthrough at Patterns.dev on compound components .

Advanced Composition Techniques

As your app scales, you’ll face new challenges. These advanced topics will give you extra tools.

Performance Implications of Deep Component Trees

Every extra layer adds work during reconciliation. To mitigate:

Image

Server Components and Composition

React Server Components let you split rendering between server and client. You can mix them in one tree, but you must consider:

  • State can’t live in server components (no hooks that use browser APIs)

  • Data fetching happens on the server, reducing bundle size

  • You’ll often wrap server components in client wrappers for interactivity

Read the Server Components RFC on GitHub .

Dynamic Slot-Based Composition Patterns

Inspired by Web Components’ `<slot>`, you can emulate dynamic slots in React:

  1. Define named areas via props

  2. Use context to register slot content

  3. Render slots by matching names

This approach shines in design systems where consumers inject arbitrary pieces:

<Card>
  <Card.Slot name="header"><h1>Title</h1></Card.Slot>
  <Card.Slot name="body"><p>Details…</p></Card.Slot>
  <Card.Slot name="footer"><button>Save</button></Card.Slot>
</Card>

Learn how to build this in a Dev.to post on component slots in React .

Composition vs. Configuration: Choosing Your Approach

Should you compose via React elements or configure with props/objects?

Approach

Pros

Cons

Component Tree

Highly flexible, type-safe in TS

More boilerplate, nested

Props/Objects

Simple data structures, less nesting

Less flexible, harder to type dynamic behavior

“When you need arbitrary JSX, compose. For data-driven UIs, configuration often wins.”

Kent C. Dodds

Cross-Cutting Concerns with Custom Hooks + Composition

Custom hooks excel at extracting shared logic. In large apps you might need logging, analytics or feature flags without altering your JSX trees.

function useAnalytics() {
  const track = event => console.log("Tracked:", event);
  useEffect(() => track("Page Viewed"), []);
  return { track };
}


// In your component
function Button(props) {
  const { track } = useAnalytics();
  return <button onClick={() => {
            track("Clicked"); 
            props.onClick(); 
         }}>
           {props.children}
         </button>;
}

You can find a tutorial on writing custom React hooks .

Putting It All Together

By combining “Thinking in React” with core patterns and these advanced strategies, you’ll build apps that are both maintainable and high-performing. Start with a clear component hierarchy, choose the right composition pattern, and layer in optimizations—whether through server components, dynamic slots, or custom hooks. Your React projects will handle complexity with confidence.

Kalle Bertell

By Kalle Bertell

More from our Blog

Keep reading