Use Component Composition to Improve the Reusability of Your React Code

If you do it right, it’s like playing with legos!

Fernando Doglio
Bits and Pieces
Published in
5 min readJul 13, 2022

--

Photo by Kelly Sikkema on Unsplash

How come we know that big functions are bad and we should favor composing bigger functions out of smaller ones to favor readability and maintainability, but we don’t do the same with our UI components?

Class components in React are a thing of the past, mind you, you might still be using them due to legacy architecture, but if you’re starting a project from scratch, I’d be willing to bet actual money that you’re going to use functional components and hooks.

Then why, if you’re using functions to define your components, are you still creating mega-components that receive a trillion props just to understand how they can be rendered?

Let’s look at an alternative to this widespread technique and try to understand why it is so much better in terms of scalability, code reuse and maintainability.

It is highly recommended to work with Bit for this.

It decoupled components from a spesific repo, and makes it easy to create and compose independent components into many applications. It will make your development faster and you can infintly reuse any components. Also, it handles dependencies so when you compose a component into another, you can later seamlessly manage updates and changes to dependant components.

What’s wrong with your components now?

Let’s first address the pink elephant in the room: your components are bloated.

Or they’re starting to be, so consider the advice given here before a huge refactor is in order.

What do I mean by “bloated”? This:

Imagine you’re building your blog — something we’ve all done at one point in our career — and you’ve created a component to list all your articles, so you use it like this:

You’re only providing yourself with a single component to tackle the entire task of displaying the list of articles, but at the same time, you’re giving yourself some customization options. This is because you’re thinking about creating smaller lists in other sections of your blog, and you’ll want to display them differently there. This is smart, you want to re-use your component.

It is, by all means, a valid approach, however, I’m sure you can start seeing in your mind the horrible logic that needs to go inside the BlogPosts component to be able to accommodate all those customization options.

And on top of that, what if you don’t want a paginator in one of these alternative views? Do you need to add yet another prop? What if you want to show 6 articles in 2 columns, and then the rest in 3 columns?

While you might think that you’ve given your component a nice degree of customization, you’ve actually made it quite stiff to changes. Any new ideas you might come up with, will require code changes. And that is bad.

So let’s see an alternative that will still let you do what you want, but at the same time, will provide the actual degree of customization you’re looking for: component composition.

If instead, you build your components separate, as individuals, you could do something like this:

With that in mind, you can take those components somewhere else, and say:

Notice how I gave you 3 different layouts, using either the same components, or adding new ones without having to modify the existing ones.

That’s the power of component composition, you’re getting a really flexible set of building blocks that you can use however you see fit.

In fact, you can later go ahead and potentially reuse some of those components with others, like the Pagination component.

Let’s see how we can use composition coupled with Context.

Component Composition using React.Context

The key to the above syntax and the ability to seamlessly compose a bigger component using smaller, individual components is React’s Context.

The new BlogPostsComponent now uses a context provider to inject the articles, and some pagination options to all the components used down the DOM tree:

And now, the ListLayoutComponent (to give you an example of what a layout could look like here), would look like this:

Through the use of the useContext hook, we access the injected properties and simply use them however we see fit. In this case, that means rendering a list of links.

And the PaginatorComponent, who’s sole responsibility is to render the page links, can use the context like this:

If you want to test this project, you can check out the full code here.

That’s it, the “trick” is simple, through the use of a context provider, you can inject properties into child components without you having to couple their implementation. Instead, if you implement a generic context provider, you can even reuse some of these components elsewhere, or even in other applications.

Do you have a better way to decouple the implementation of components in a way that they remain related but can vary significantly without affecting one another? Share it in the comments!

Bit: Composable app development

Say hey to Bit. It’s the #1 tool for component-driven app development.

With Bit, you can create any part of your app as a “component” that’s composable and reusable. You and your team can share a toolbox of components to build more apps faster and consistently together.

  • Create and compose “app building blocks”: UI elements, full features, pages, applications, serverless, or micro-services. With any JS stack.
  • Easily share, and reuse components as a team.
  • Quickly update components across projects.
  • Make hard things simple: Monorepos, design systems & micro-frontends.

Try Bit open-source and free→

--

--

I write about technology, freelancing and more. Check out my FREE newsletter if you’re into Software Development: https://fernandodoglio.substack.com/