Part I: Keep your application organized
- Break down your application in meaningful parts
- Reflect the defined application parts in code organization
Before actually starting talking about components’ code,
let’s step back and think about applications as a whole.
Modern web-apps are often complex, sometimes dealing with multiple products living in the same React application.
This leads to a lot of components, which are sometimes related, sharing the same state or independent.
A disorganized react application results in:
- Slow navigation in the codebase and consistency issues
(mental model) - Difficulties to refactor
- Harder on-boarding for new-hiring
Example
Let’s take a React application with two different products: a marketplace and project management.
This application allows you to ask for a quote to freelances of the public marketplace to finally invite them to collaborate in private on the project management tool using a system of chat and conversations.
To illustrate the product complexity of the application, let’s take a look at all the features related to the Projects across the products:
- list all projects of a workspace
(project management) - talk about a project in a dedicated project chat
(project management & marketplace) - access the project timeline and create posts to collaborate
(project management) - add freelance profiles to a project shortlist for hiring phase
(marketplace)
Those features led to a lot of contextual project components:
- Project chat title
(project management & marketplace) - Project header
(project management) - Project listing item
(project management) - Project shortlist item
(marketplace) - Project thumbnail
(project management) - Project actions buttons
(project management)
As you can see, Project related components, present in the different parts of the products have different logic and states:
- Project chat title needs the project information but also the members of the conversation — which is a subset of the project’s members.
- Project shortlist item needs the current freelance profile to create a quote for the project using the APIs.
Let’s ensure that our application is consistent, easy to navigate, by:
- Break down your application in meaningful parts
- Reflect the defined application parts in code organization
1. Break down your application in meaningful parts
Identify and define your application parts is important on many levels:
- properly splitting the state into the global state (redux/mobx), feature-related state (by using React context) and component state (hooks)
- ease navigation by adopting a proper folder structure /component organization
- Avoid documenting your component organization by having a clear and coherent structure
Coming back to our application example, a proper break down of our application into meaningful part could be the following:
Our example React application divided into multiple products and contexts
How to break down your application in meaningful parts
This work is also known as
Domain-Driven Design: architecting your application by breaking it down into “domains” (a domain is an area of knowledge,
ex: the marketplace)
However, let’s skip the theoretical part and see smoother practical approach to define your application parts:
Luckily, this “break down” work is already mainly done by your product & design team members, simply because, in web-apps, components are often matching features and UI definition.
Then, from the UI/product features definition, see how it matches with the technical aspect of the application (state, routing, etc.).
Then, if necessary, redefine the parts by splitting, merging them, or adding sub-parts.
2. Reflect the application structure in the code organization
We now have a way to define your application’s parts.
Let’s use this structure to improve our application organization.
Folder structure
Folders structure is, of course, very team dependent — tastes dependent — but here is a suggestion:
- colocate logic, helper, custom-hooks
If some of your logic (helper, custom hooks) is only used by a component or a feature, make sure to locate it at the nearest shared folder.
- extract global purpose components into a dedicated folder or library
ex: if you have UI-kit, don’t put it in src/components, but rather in src/ui-kit/components
- Tips: the myComponent/index.tsx, myComponent/style.scss the structure feels natural but does not play well with VSCode Quick file navigation.
Prefer explicit structure: myComponent.tsx, myComponent.scss
VSCode Quick file navigation gives a higher match on filenames than folders
Naming convention
Thinking on how to name a component will force you to actively think about the place of the component in the app and its responsibilities.
A component hard to name is like a component hard to test: it might “do too much.”
Component naming is not exclusively about consistency, it is actually a very good design exercise.
Example of component naming that may lead to over-generic, meaningless components:
- View
(even if in the folder ProjectList/) - EntityForListItem
- Modal
- Main
Let’s see, for our example application, some examples of component names that highlight: location in the app, scope, and responsibilities:
- ChatConversationName
- Sidebar
- MarketplaceAddToShortList
- ProjectForm
Each component’s name carries, when necessary, some essential information about the location (ex: MarketplaceAddToShortList) or scope (ex: ChatConversationName)
Conclusion
- Identifying the parts (domains) of your application will definitely help to shape a better architecture (ex: state).
- Investing a small amount of time in finding a proper component’s name is a good design exercise that will bring consistency (location and well-defined responsibilities)