ReactSmallTips: Open-closed React components

Ramon Prata
5 min readAug 10, 2022

--

At some point in your career as a software developer you might start worrying about not just write a code that works, but a code that is readable, easy to understand, easy to maintain and scalable. In other words, a good quality code.

In order to achieve that, there are some guides like: patterns, paradigms and principles. Those guides were designed by real developers to solve well known real problems in programming. Among them, we have SOLID Principles.

SOLID is an acronym for the first five object-oriented design (OOD) principles by Robert C. Martin (also known as Uncle Bob).

The SOLID acronym stands for: Single-responsiblity Principle; Open-closed Principle; Liskov Substitution Principle; Interface Segregation Principle; Dependency Inversion Principle.

If you search for SOLID principles, you’ll probably find a lot of examples usually using classes (OOP). But the concept, the ideas behind the principles are not restricted only to classes. In this post we will focus on the letter O (Open-closed Principle) applied to a React Component.

So, what Open-closed Principle is all about? The idea here is that..

The objects or entities should be open for extension but closed for modification.

So, if we bring this concept to the React world, we can think of components as objects or entities. That means it would be a good practice to create components open to extension, but closed to modification. At least the reusable ones

So let’s see a scenario where we can apply this principle in a reusable React Component. In most applications, specially mobile ones, we see a “thing” that is present in almost every screen: the Header.

At the beginning of the project, that Header might be a simple “box” with some style and a logo:

And your code will be as simple as the Header needs

But as the application grows, that Header will need some changes: a button/icon to open a menu, to navigate; an input text where the user can search for something and more:

If we don’t think about the Open-closed principle here, we’ll end up making changes to the Header component every time a new feature comes up. And our code will start to get a little messy

Now we know we can do better using the Open-closed principle. But how? Like I said, the concept is not restricted only to classes, so we can implement the principle using approaches more suited to functions and components. Those approaches are already in React docs, I’m talking about: Composition & Specialization. So let’s do that..

First, let’s create the OpenClosedHeader

As you can see, the Header keeps its structure and default style, but it is now truly context-agnostic. We can have something on the left side, some children components in the middle and something on the right side, but everything is optional. That means, we have a component that is open for extension but closed for modification. We don’t need to change it for every new feature. But how can we extend this component? Well, we can use the Specialization approach mentioned before.

Let’s create a HeaderTitle. A component that uses the OpenClosedHeader behind the scenes, but it renders a title instead of hard-coded Logo component

As you can see, our Specialized Header accepts a title that can be a simple string which will be rendered in an <h4> HTML tag, or it can be a entire new component. Note that it also accepts and forwards all the props that OpenClosedHeader takes. And we can use it like this:

But this is too basic, let’s make a more interesting Specialized component..

Using HeaderNavigation

And more interesting: Since our HeaderNavigation is a specialization of OpenClosedHeader, we can simply pass a complete new component as children to it..

To sum up. In order to implement the Open-Closed principle, we created a really flexible component OpenClosedHeader. This component can be extended (Open) and it doesn’t need to be modified every time we face a new scenario (Closed). We only have to think about the most common cases in our application and implement Specialized versions of the original component to cover that cases. For very specific cases that the specialized components doesn’t cover, we still can use the basic OpenClosedHeader (with its default layout and behavior), and pass an entire customized component as children to it.

I hope this post was useful and helps you to write better components using good practices like the Open-Closed principle.

Thank you. Cheers!

REFERENCES

  1. SOLID Principles — By Digital Ocean
  2. React docs

--

--

Ramon Prata
Ramon Prata

Responses (2)