As you’re working with React.js or React Native, you’ll quickly notice the ✨magic✨ and flexibility that comes with components. Components save us a great deal of time by breaking down the user interface into reusable code while the component architecture makes our code easier to read and understand.
Taking Component Organization to the Next Level
To further these ideas, we can break our components into two categories. These two categories have several names with slightly varying concepts but all share the same core idea. The original idea of dividing components was coined by Dan Abramov where he called them smart and dumb but later revised them to be called container and presentational components.
This concept has been embraced and expanded on by the React community. Aside from smart and dumb as well as container and presentational, you might have heard of them as functional and class components, fat and skinny, screens and components, etc. In this article, we’ll be referring to them as smart and dumb components.
What Makes a Component Smart or Dumb?
Smart components are app level components that perform functions and manage data while dumb components focus solely on the UI.
Before we dive into the defining characteristics of smart and dumb components, take a moment to think about which components in the sign up form below would be considered smart and which would be considered dumb.
🤓 Smart components focus on how things work.
Common characteristics of smart components include:
- Manipulates Data Smart components can fetch, capture changes and pass down application data.
- Call Redux, Lifecycle methods, APIs, Libraries, etc These components are called smart for a reason! They are responsible for calling libraries and functionality.
- Manage state Smart components are responsible for managing state and knowing when to re-render a component.
- Rarely includes styling Since dumb components focus on styling, it allows the smart component to focus on functionality without the clutter of styles too.
🦄 Dumb components focus on how things look.
Common characteristics of dumb components:
- Focus on the UI Almost all basic UI components should be considered dumb components. Examples include loaders, modals, buttons, inputs, etc.
- Accept props Dumb components accept props to allow them to be dynamic and reusable. For example, you might send the title of a button in props from the parent component to allow it to have a unique name.
- Require no app dependencies Other than UI packages, like
Reactstrap, dumb components do not require dependencies.
- Rarely include state The only instance where a dumb component has state is for manipulating the UI itself, not application data. Some examples of where a dumb component might have state would be button groups, tabs, switches and other UI elements that do not impact the data, only the UI.
Let’s take a look at our sign-in form example from before. Almost every component can be a reusable dumb component including the container, header, inputs and button.
Benefits of Dividing Components
✨ Reusability ✨
Though we can write out a similar component multiple times in different locations of an app, we can save a great deal of time by building a reusable component that accepts props.
Think of an app that includes sign up, sign in, forgot password, account settings, and for kicks, an event sign up form. That’s a lot of inputs! Rather than building this input out for every required instance, we can create a reusable dumb component to import into each screen and send props from the parent component to make each input dynamic.
✨ Flexibility to easily make changes ✨
Separating smart and dumb components allows flexibility to make both small and large changes to the app without a great deal of tedious work.
Let’s think about our example above for a second. What if we wanted to add or even change the color of the border of the inputs for the entire app. If we weren’t using a dumb component for our input, we might need to change that border in every single spot the input was located. Since we made a dumb component for the input, we only need to change the border in the one place for the entire application.
✨ Code readability ✨
Simply put, the less code you have and the more organized your code is, the easier it is for not only you to understand your code, but for others to dive-in and understand what’s going on.
✨ Provides consistency & prevents duplication ✨
As we build applications, it’s so very easy to duplicate ourselves and others on a project, or even rebuild something that wasn’t needed in a completely different way. By having a strong grasp of what smart and dumb components are, we can create organization so that we always know where to look for our reusable components, and have set standards as to how those components are used.
✨ Simplifies UI decisions ✨
Since all of our UI components are separated into dumb components, we can easily dump all UI components on one screen where your client, web designer, or graphic designer can see everything at once.
✨ Easy to test ✨
Dumb component are very easy to test because they simply take-in props and return a piece of UI. This makes for very straightforward unit testing for dumb components.
When to Start
Whether you’re just starting a new project or are years into the project, it’s never too late to start implementing this type of component separation.
Generally when starting a project, I like to create folders in my
src folder to organize components before even beginning to build a first component. This process requires us to think about the functionality and the future of that component. Others suggest starting to exclusively build dumb components until reaching a point where you’re passing down too many props.
Of course if this is an old project where you’d like to implement this organization, a good ole’ refactor may be just what the doctor ordered. I recommend starting small and slowly replacing repeated UI features and building up to the overall concept.
🎉 Did anyone say refactor party?!