Composition and Inheritance: A React Story

Mike Diaz
3 min readApr 11, 2020

The first time I read through the legendary React Docs, I didn’t understand the importance of section 11 in Main Concepts: Composition vs Inheritance. After taking more time to study React, the difference between these two concepts and the reason why one might be preferred over another became more clear.

What are composition and inheritance?

Short answer: they are means of transmitting attributes that are shared by multiple objects. Here’s a classic Javascript inheritance example:

class Store {
constructor(name, city) {
this.name = name
this.city = city
}
greeting() {
console.log("Hello and welcome to " + this.name)
}
}

I’ve got something big and general. So what if I want something more specific, like a grocery store?

class GroceryStore {
constructor(name, city, discountFruit) {
this.name = name
this.city = city
this.discountFruit = discountFruit
}
greeting() {
console.log("Hello and welcome to " + this.name + ". ")
}
shareDiscount() {
console.log("Our discounted fruit today is " + this.discountFruit)
}
}

Our code is growing, but since we’ve already got Store giving us logic for things like name and location, we can ask our GroceryStore to inherit those attributes:

class GroceryStore extends Store {
constructor(name, city, discountFruit) {
super(name, city)
this.discountFruit = discountFruit
greetingWithPromotion() {
console.log(super.greeting() + "Our discounted fruit today is " + this.discountFruit + ".")
}
}
}

Nice! The super inside of constructor allows us to assign the name and city attributes in the exact same way our parent class, Store, would. Since Store doesn’t have a discountFruit attribute, we assign that manually. We can also use super to reference methods from the parent class.

Okay, so this seems to be working and is certainly useful. So why do Dan Abramov and the React Docs suggest always using composition over inheritance? After doing a bunch of research, I’ve come to the following conclusions:

  • Composition is more flexible and customizable
  • React was built with the intention of composition behind it, so it’s best to stick with that.

Here’s a display of a react component and composition at work:

//App.js
import React from 'react'
import Bicycle from './Bicycle'
const App = () => {
return(
<div>
<Bicycle weight=8 ring={() => console.log("ring ring!")}
</div>
)
}
export default App

In my app file, I call on a Bicycle component and assign it some properties. We can see that they are weight (an integer) and ring (a function). Here’s what the Bicycle component looks like:

// Bicycle.js
import React from ‘react’
const Bicycle = (props) => {
return(
<div>
<h1>My Bicycle</h1>
<p>This is my bike. It weighs {props.weight} lbs.</p>
<button onClick={props.ring}>Click me to ring the bell</button>
}
export default Bicycle

This component will render a “Bicycle” to the page. The user viewing the page will be able to see the text that describes the bicycle and click a button that triggers a “ring” function. This is because React components allow us to compose objects, like I did in App.

This works the same way as inheritance, but it’s so customizable and straightforward. You can clearly see in App what attributes I’m assigning and what they’re called. No need for super() or .protoype or extra lines of code within your child class to re-declare a function that was passed down. Composition is also incredibly useful in that it can create higher-order functions and even higher-order components, leaving limitless possibilities for customization and efficiency maximization.

--

--