All articlesSoftware Design

Why Composition Beats Inheritance In React

Learn the benefits of using composition over inheritance in React projects. (3 minutes)

Petar IvanovPetar Ivanov
3 min read
On this page

A month ago, I shared an article about writing extensible components in React by following the Open-Closed Principle.

I slightly touched on the importance of preferring composition over inheritance when crafting UI components.

If you want to create UI components that grow with your app, choosing the right strategy from the start is crucial.

In today’s article, I’ll dig deeper into the importance of using composition over inheritance.

Even React’s team recommends this approach: “composition over inheritance”, which aligns perfectly with OCP.

If you missed the previous article on Open-Closed Principle (OCP) In React: Write Extensible Components, check it out here:


The Limits Of Inheritance

Let’s imagine a simple <LoadingButton /> built by extending our base[<Button />](/blog/open-closed-principle-ocp-in-react-write-extensible-components/) from the previous article:

TSX
<strong>// Inheritance-based approach (less flexible)</strong>

<strong>class LoadingButton extends Button</strong> {
  render() {
    return (
      <Button className={this.getButtonClass()}>
        {this.props.isLoading && <Spinner />}
        {this.props.children}
      </Button>
    );
  }
}

Even though it looks okay at first, there’re a couple of problems with this approach:

  • Tight Coupling - every change in the &lt;BaseButton /> logic risks breaking the &lt;Button /> subclass.
  • Flat Hierarchies - adding new variants leads to a growing class tree.
  • Hard To Mix Behaviors - combining features like icon + loading needs new subclasses.

How Composition Works

The main idea behind composition consists of two steps:

  1. Break the UI into many smaller reusable components.
  2. Combine these reusable components into more complex components.

You can learn more about how to turn your UI design into React Components here:

This way, you have multiple smaller building blocks which can be reused across the codebase to fulfill different use cases.

TSX
const <strong>LoadingButton</strong> = ({ isLoading, children, ...restProps }) => (
    <Button {...restProps}>
        {isLoading && (
            <Spinner />
        )}
        {children}
    </Button>
);

// or

const <strong>BackButton</strong> = ({ navigateTo, ...restProps }) => {
    const navigate = useNavigate();

    const handleClick = () => {
        if (navigateTo) {
            navigate(navigateTo);
        } else {
            navigate(-1);
        }
    };

    return (
        <Button
            {...restProps}
            onClick={handleClick}
        >
            <FontAwesomeIcon icon={faLongArrowLeft} />
        </Button>
    );
};

Benefits Of Using Composition Over Inheritance

The composition based approach:

  • Makes components open for extension through props, render functions, etc.
  • Keep base components closed for modification.
  • Allows for unlimited mixes of behaviors and combinations.

This is how the idea of “composition over inheritance” aligns with OCP.


📌 TL;DR

  • Composition keeps core components unchanged and lets you add features via props or small wrappers.
  • Inheritance forces new subclasses for each variant, leading to less flexible components and more code.
  • By using composition, you can mix different behaviors like <LoadingButton />, <BackButton />, etc, without touching the core/base components.
  • Prefer Composition over Inheritance in React projects.

Related articles

Whenever you’re ready, here’s how I can help you:

  1. 1.

    The Conscious React: React architecture, design & clean code — 100+ production tips across 6 chapters, updated for React 19, plus 4 companion repos you can clone and run.

  2. 2.

    The Conscious Node: Node.js architecture, design & clean code — 157 production tips across 10 chapters, from module boundaries to the transactional outbox and zero-downtime deploys.

  3. 3.

    The JavaScript Architect Bundle: Both books + all React companion repos + CLAUDE.md rulesets + both playbooks. The complete path from developer to architect.

  4. 4.

    Free Resources: Architecture playbooks, cheat-sheets, and the JavaScript Architect Roadmap — practical guides for leveling up to senior.

The T-Shaped Dev

Join 30K+ engineers leveling up to architect

One practical tip on JavaScript, React, Node.js, and software architecture every week. No spam, unsubscribe anytime.

Petar Ivanov

Written by

Petar Ivanov

Software engineer, author, and speaker. I help JavaScript developers grow from Mid → Senior → Architect — production-grade React, Node.js, and AI systems.