We are always excited about the new shiny things that come out every week in the programming world, from new ways to structure components to new techniques to reduce those two lines of code.
But in the real world, things are not so shiny. We often have to deal with codebases that have evolved over many years and components that bear the marks of many different developers.
Our story is about a component that has 2700 lines of code. Let’s try to explain how things went south and how we can do better.
I am currently working for a company with a dashboard that has a fleet management tool that shows vehicles roaming around a city in real-time.
The dashboard component is the hero of our story today. It has many functionalities, but none of them are super fancy:
- A map that shows the vehicle markers
- A way to search for the vehicles
- A popup that shows each vehicle’s details when clicked
- A list of vehicles at the bottom
- Some filtering options
Sure, there are several features that this single component is responsible for displaying. But is it really enough to need 2700 lines of code?
Obviously, it would be stupid of me to paste 2700 lines of code into this article. (Also, it would be illegal 😓 .) But, let me show you the general structure of the component:
Okay, now tell me what’s wrong here
To be 100% honest? Almost everything. Let me explain:
This is an obvious one. Unfortunately, I have seen many examples of it throughout many companies and many components.
Keep the constants in a separate file
It doesn’t matter if they’re being re-used or not, it’s still better to store constants in a separate file. Down the line, someone else will create a separate constant with the same value, which will eventually create confusion.
I do it this way:
Then I import them into my component:
For this particular component, it isn’t a big deal, but best practices are best practices.
Styles and helper methods
I think it’s a very common mistake (and sometimes allowable thing to do) to put the styles and helper methods in the same file for smaller components.
If your component is only 30–50 lines of code, it can make sense to keep the styles and helper methods in the same file.
But, having 580 lines of style declaration doesn’t make sense in any scenario. You won’t need to touch these styles very often.
I follow the following folder structure to keep things organized:
The responsibility of the files is clear from the names of the files themselves. It’s simple to split our massive component to one-third of its current size just by putting things where they should be!
If you are using Raw CSS or SCSS, you probably don’t make this mistake, but projects using styled-components or material-ui mostly follow this bad practice.
Once someone started it, it became the standard practice.
Don’t fall into this trap! Create a separate file for styles ahead of time; this can save your component in the future.
There are two types of components:
- Dumb components → Only act as a container or view.
- Intelligent components → Show something based on logic.
There is no reason to put two components in the same file. It directly violates the Single Responsibility Principle.
Every class or component should do one thing and one thing only
Sometimes we get lazy, myself included, and put simple container components into the actual component. But, what will the next developer think when they read this component?
Will they move the smaller component into its own file?
Umm… Probably not. So after 4–5 years, you’ll have 200 lines of helper dumb components that can be easily extracted into separate files.
I’m not sure if you noticed, but this massive component is using ClassComponent. I’m sure you know the reason; it was written at a time when functional components were not that common.
Nowadays, using functional components makes more sense:
- They’re easy to maintain
- They use less code
- They’re (arguably) more performant
But even I wouldn’t try to convert this component into a functional component at this stage. We need to refactor a lot of things before converting it into a functional component.
Results of easy refactors
Let me show you an estimation of how much we can improve without understanding what this component is doing.
We can just export the constants to constants.ts , styles to styles.ts and helper methods to helpers.ts.
This will take us two hours of work max; all we need to do is put things into the appropriate files and then import them.
We can reduce a component from 2700 lines to 1300 lines!
Some may say that’s still a lot, but hey!!! One step at a time, right?
Can we do better?
Yes, of course. When we look into the internal logic, we can reduce the component even further if we:
- Break the actual components and re-usable parts into even smaller components
- Use a functional component
- Take advantage of hooks
- Use functional redux
And so on… But that’s a story for another day.
Show me the good parts
Obviously, this component has lots of problems, but it has some good things going on, too.
Although the type declarations add up to 200 lines, they’re worth it. Without Typescript, it would be impossible to maintain this component.
Some of the dumb logic is extracted from the view logic itself. For example, showing a message based on vehicle status:
It’s better to have them in a separate function instead of writing the logic into the view, which can look something like this:
So, it’s not all bad, and some developers definitely tried to do things the right way. At the end of the day, development is a team effort.
What did I learn?
The biggest takeaway for me is the importance of following best practices.
Best practices are there for a reason!
The impact of following best practices may not be evident on the first day, but if you disregard them, you will feel the pain someday!
If you are interested in staying up-to-date on new developments through technical articles like this, be sure to subscribe to the Pieces blog to get updates on weekly articles. And, check out Pieces, the fastest, smartest AI Assistant for code snippets and screenshots, which has personally made me more productive!
Become more productive writing your React apps
Every component you create in React often requires tons of repetition no matter what you do, and across every frontend project, there are always custom setups and best practices teams follow. Pieces helps you solve this for any React project by allowing you to create a local micro-repository where you can store any code snippets along with relevant metadata straight on your machine. Additionally, Pieces makes it incredibly easy to share your snippets with others, form collections to onboard others onto a project, and even has integrations to allow you to use your snippets directly in your IDE.