Rethinking Atomic React: an interpretation of Brad Frost’s Atomic Design to use in React projects

Atomic Design is a very widespread topic nowadays within the front-end community, but while looking at several projects, I realized that there is still  a lot of personal opinion on its implementation, and here I list some points that caught my attention throughout the years.

This article is not a tutorial on how to create your applications but it is intended to share my interpretation on how to best use this amazing methodology.

First, what is Atomic Design?

A methodology created initially by Brad Frost, in which he took inspiration from chemistry and brought it to applications and the way to develop. Initially, it focused only on the design and eventually reflected and “revolutionized” front-end architecture as well. In Brad’s own words:

Atomic design is methodology for creating design systems. There are five distinct levels in atomic design: atoms, molecules, organisms, templates and pages.

Atoms: are the basic structure of matter, applied to web atoms are like HTML tags, a label, an input or a button.

Molecules: They are a group of atoms put together with basic fundamentals of a unit. They serve as the basis for the design system. For example, a label, input and button together making a form element.

Organisms: They are blocks of our system, where we can group molecules together to form relatively more complex components, a section of the application.

Templates: They are mostly a group of organisms put together to form a final structure, this is where we begin to see the layout in action.

Pages: These are instances of templates where “gaps” are filled with content, resulting in the final view that the user will see.

atomic-react
Based on the definitions above, we will now enter the world of code. What I intend to bring is my interpretation of how to apply these concepts within our applications.

Problems

I know there are several examples of atomicity out there, so I want to focus on the problems I encountered during my experiments while working with React, showing some concepts and an example of code that you can find linked at the end of the article.

* Duplicate Behavior (mainly between molecules and atoms)

* Inability to reuse code between projects

* Lack of visibility and understanding of component state

* Great impact on development time by creating more components than needed

* Difficult code maintainability due to lack of standardization

Well, let’s talk about each item separately, starting with: Duplicate Behavior. What I’ve noticed looking at various projects is that even though they are different code, components often have the same behavior. As in the case of forms components, where we tend to create a component for each form of the application (form-client, form-company, form-xxxx,…) and they perform the tasks in a similar way. Why not create a single, more detailed and worked form component that can abstract all of these components? It’s easier to avoid abstraction and simply implement specific behavior in duplicated components, and that’s what greatly impact reusability within a project.

Inability to reuse code between projects is a very important thing for a company and its developers. Does rewriting all the code with each project mean your code is not good enough to use again? The problem I see here is related to where to put your application’s business rule. Continuing with the forms example above, your component should not be aware of the backend API let alone fetch the data. As stated earlier, components are “dumb” elements. Your entire business rule, functions that are “injected” into your components, must come from the business rule layer (pages, containers, services). This way you can move your code between projects, taking only what interests you.

The lack of visibility and understanding of component state is very particular and will vary widely among developers. Using a list of users as an example,  I want to highlight that it may be hard for another developer to understand the component’s usage and behavior just by its name if you add other things to the component, like API requests to fetch users information and/or handling the Redux state for it. At that point, we lost all the intuitiveness of the component as it became a piece of application, no longer a simple component.

Considering that you develop your components by duplicating behavior or injecting business rules into them, at some point on the project you may have a big impact on development time by creating more components than necessary. Why do I say this? Because there are situations, that happen more often than we want, in which small fixes impact in  changes on dozens of components or even API changes to break the entire application, and that can cause a giant rework during the fix. In addition to it, if your projects are reusable, planning will give you much more accuracy on time and scope management.

Last but not least, difficult code maintainability due to lack of standardization is something that happens all the time, since every project gets refactored, and every week there is a new library available, a React update (now all components have hooks, now each one has useState), etc. Don’t get me wrong, code must be updated, but before that, it must be thought through, standardized and then evolved.

OK! What tips can I share?

  1. Firstly, while reading the Atomic design components definitions, the first thing I realized is that Pages are not components, as these are just instances of Templates, and the pages should be closer to the service layer of your application, so:

pages

  1. Speaking of components, I believe they should be “dumb” and should not be aware of your application’s business rule and only render what they were asked to do. Don’t use Fetch/Axios, properties that can’t be overridden or anything related to your application inside the component.
  2. Inject the dependencies of your project. A very common thing is to use high impact external libraries within components, such as:

import {Link} from ‘react-router-dom’

Avoid this within its components. It may be that you won’t use the sample library above in every project and you will lose component reusability.

  1. Start the component small, but once you get the chance to improve it, do it! And don’t duplicate the same behavior in different components, like the form example mentioned previously.

All the items discussed above are very conceptual. I am sharing this link: https://github.com/natamvo/rethinking-atomic-react where I started a React application (react-app) and created some sample components in order to make the points raised above clear.

 

About the author.

Natam Oliveira
Natam Oliveira

VP of Engineering at Cheesecake Labs - IA / IoT enthusiast. Go bravely where no one have never gone before!