DEV Community

Cover image for How to organize your components using the Atomic Design

How to organize your components using the Atomic Design

Giuseppe on November 12, 2019

Often, when you start the development of an application, you can get in trouble trying to understand how to organize your components. In this post...
Collapse
 
jsardev profile image
Jakub Sarnowski

Atomic design didn't work for me actually when using it with React. It makes finding the components harder than just using a flat, or feature-based structure. Let me give an example:

We have a Button component. It's a dumb component doing nothing, so we probably put this into Atoms. Now, I want to have an IconButton, which uses Button, so we'll put it to Molecules. Next, let's say we have a SubscriptionButton, which opens a newsletter subscription modal - this is a lot of logic, so we'll put it to Organisms. Now, it was not obvious for me or my co-workers (and especially newcomers) where should we look for the specific component. It very quickly became a mess.

IMO a lot clearer is a structure based on features. Basing on the earlier example, Button and IconButtons would be just Components (where all reusable, dumb components land), and SubscriptionButton would be somewhere in a Subscriptions folder, along with things like SubscriptionModal, SubscriptionModalCloseButton etc.

Collapse
 
sanfra1407 profile image
Giuseppe • Edited

Hi Jakub,
thank you for your comment: I really appreciate it!

I'm not saying that the Atomic Design is the panacea to all evils (it has some limits of course). What I wrote is that it can help you to think in reusable components way.

Let's say we have a `SubscriptionButton`, which opens a newsletter 
subscription modal - this is a lot of logic, so we'll put it to Organisms.
Enter fullscreen mode Exit fullscreen mode

I think this approach is not correct: the SubscriptionButton shouldn't have any kind of logic, but it should have a trigger prop to be used for launching events (in your case opening a Modal).
The SubscriptionModal should be a different component and, using React, the best scenario could be something like:

<SubscriptionModal>
<!-- A subscription form-->
</SubscriptionModal>
Enter fullscreen mode Exit fullscreen mode

I would put the logic part in the component which wrap both SubscriptionButton and SubscriptionModal.

const _handleModal = () => {
   this.setState( prevState => {
      return {
         subscriptionModalOpened: !prevState.subscriptionModalOpened,
      }
   } 
} )

render() {
   const { subscriptionModalOpened } = this.state;

   return (
      <>
         { subscriptionModalOpened ? 
            <SubscriptionModal closeModal={ _handleModal } /> :
            null;
         }
         <SubscriptionButton trigger={ _handleModal } />
      </>
   )
}
Enter fullscreen mode Exit fullscreen mode

What do you think? 🙂

Collapse
 
jsardev profile image
Jakub Sarnowski

I agree! I think that I didn't use a proper example for this 😄 I used Atomic Design in a project a few years ago and I forgot already about the specific cases where we struggled with using it.

I don't say it's a bad pattern, it just didn't work for me for some reason 😄

Oh, forgot to mention: your article is great!

Collapse
 
wvandam profile image
Wouter van Dam

While I am a fan of applying atomic design to components, I have to disagree with you about it helping with code organisation - at least in the manner you propose.

At first it does help, when the application is small. However, down the road - when the application is larger and you get back to a feature after 6 months - not having the related components together creates mental overhead.

For our next project we will keep using atomic design, but we're looking into better ways to organise our components. We'll probably go back to feature folders and depending on the size of the feature the components will be either prefixed or put in subfolders according to their atomic type.

An added benefit is that it's a step closer to breaking a feature out into a separate npm package.

Collapse
 
floede profile image
Janus Hasseriis • Edited

Is there a particular reason for making a text component?
35 lines of code just to render a <p> or <label> seems incredibly overcomplicated.

Collapse
 
sanfra1407 profile image
Giuseppe • Edited

Hi Janus,
thank you for your comment: I really appreciate it!

I can get your perplexity about the "overengineering" of the Text component.
Let me try to clarify your doubts.

The Text component in this context has too much implementation, it's true. Just two things:

  • This is a simple example;
  • This is a small application.

Having a component like this can bring some advantages.

Consistency

You have to think the this component is meant to be used and used and used... If you need to use it several times, then you must a have a consinstent component with the same size, the same font-family, the same color and so on. It's really hard to have this kind of consistency without using a component.

Let me give you one example:

<template>
   <span class="text-component size-big weight-medium family-primary color-secondary">
      {{myAwesomeText}}
   </span>
<template>

This means that, when you need to write something, to have texts which are consinstent you have to apply the same classes. Everytime. And this is not a smart approach neither stable, because it's very buggy (try to imagine what could happen writing the weight-medium class 50 times).

Automatic updates

Futhermore, with a reusable component, if you want to change a class or a default value, you just need to modify the component itself and the changes will be automatically reflected everywhere.
Having reusable components is very useful, especially in design systems.

Anyway, I want to give you a suggestion: do not put your focus on the Text's implementation; put it on the usage. The implementation is made only once, but the usage might be done n times.

Collapse
 
floede profile image
Janus Hasseriis

I'm sorry, but I don't think your example makes sense.

Of course, reusable components are useful. Very much so.
But you are talking about making an entire component only for text elements.

In your post, you describe making a molecule that combines a label with an input. That's fine.
But you gain nothing from having the label as a generic text component with type=label over just writing <label class="input-field__label"/>.
Everything you said about changing the label in one place still applies.

And if you want to have consistent <p>'s you put a standard style for paragraphs in your stylesheet.

Your long example of five different classes implies that a <span> could have other classes. That would be exactly the same with a text component type=span.
So again, it's not actually simpler.

But of course, you should write your code however you see fit :-)

 
sanfra1407 profile image
Giuseppe

And that day you'll have to search and replace it in the whole code. ;)

Collapse
 
luardo profile image
Luis Eduardo

How would you bind the events which are concerning the input fields? Would you bubble up all the events?
Or let's say I want to dispatch an action to my reducer. I should do this from my smart component while the Button (dumb component) is a child 3 levels bellow. So, when I click this button, should I have an onClick event that will go from the atom and then to the molecule and then to the organism and then to the page? Or how would you solve this?

Collapse
 
monas profile image
Laimonas

What if one day You will decide to use some Bootstrap component instead of simple input? Or some other component library like Vuetify? Having this seperation gives You a freedom to do it very fast and easy. This is the point of having own abstraction.
By the way iconButton could be considered as molecule which cosists of button atom and icon atom ;)
Naming stuff well is hard and if You can put some system in place for that it can payoff in a large long term project. It is very easy to go wrong with component spliting. I have seen it many times. So if you think that things will never change think twice.

Collapse
 
enderimen profile image
Ender İMEN • Edited

Hello, first of all thank you for this beautiful article. It is a method I use frequently. But there are a few questions in my mind I will be glad if you answer my questions. When we divide the components as you mentioned, it would be more correct to write the css of the element in the related component. Is it in our global css file or in direct component? Like style-scoped. And if we do it this way, for example, if I will use the button component in three places on the home page, will it be duplicated three times? Thank you.

Collapse
 
lico profile image
SeongKuk Han

Thank you for sharing the good post

Collapse
 
lordsayur profile image
Omar

In app.vue, how are we going to create 2 way binding between the input data inside the component with data declared in app.vue?