Context
Creating a React-based application can be daunting because React doesn't provide certain directory structure. Many people have their own structures. Like them, I have my own opinion as well.
Component Hierarchy
I view components based on their usage. In general, I see 3 types of components -- common, feature and page.
Common components are components that can be used in a generic fashion like Button
, Modal
, Accordion
, etc. These components are meant as building blocks of your application.
Feature components are components that is used by a specific feature. You can view features as an offering you provide for your users. A feature component can be Authentication
, User
, etc.
Lastly, page components are components that allows users to use your features and common components. These could be Settings
, Profile
, etc.
Dependencies
The three types of components have a set of rules on how they could interact with each other.
Common | Feature | Page | |
---|---|---|---|
Common | ✅ | ||
Feature | ✅ | ✅ if same feature | |
Page | ✅ | ✅ | ✅ if same page |
✅ - can use component
The reasoning for the rules is because we want a separation of concerns between the different tier of specificity. What I noticed after an application gets bigger, many components become intertwined into other places.
Advantages of structuring your following the three tiers are:
- Semantic naming of directories makes it easier to visualize the codebase and for new engineers to understand it.
- Absolute paths using aliases will be more understandable.
import { Button } from "@common/Button";
import { Dropdown } from "@common/Dropdown";
import { UserAvatar } from "@features/User/components/UserAvatar";
- Building new pages will be simpler because you won't need to worry about where your core functionality will live.
- This will urge designers and engineers to be more consistent or use existing components since the structure is meant for reusability
Example:
app/
|-- common/
|-- Layout/
|-- __tests__/
|-- stories/
|-- index.ts
|-- Layout.tsx
|-- Layout.scss
|-- Button/
|-- __tests__/
|-- stories/
|-- index.ts
|-- Button.tsx
|-- Button.scss
|-- Modal/
|-- __tests__/
|-- stories/
|-- components/
|-- ModalHeader/
|-- index.ts
|-- ModalHeader.tsx
|-- ModalHeader.scss
|-- ModalContent/
|-- index.ts
|-- ModalContent.tsx
|-- ModalContent.scss
|-- ModalFooter/
|-- index.ts
|-- ModalFooter.tsx
|-- ModalFooter.scss
|-- index.ts
|-- Modal.tsx
|-- Modal.scss
|-- features/
|-- User/
|-- __tests__/
|-- stories/
|-- components/
|-- UserAvatar/
|-- __tests__/
|-- stories/
|-- index.ts
|-- UserAvatar.ts
|-- UserAvatar.scss
|-- hooks/
|-- useUser.ts
|-- useUserMutations.ts
|-- constants.ts
|-- helpers.ts
|-- pages/
|-- Settings/
|-- __tests__/
|-- components/
|-- UserTab/
|-- __tests__/
|-- stories/
|-- index.ts
|-- UserTab.tsx
|-- UserTab.scss
|-- index.ts
|-- Settings.tsx
|-- Settings.scss
Other files/directories that can exist within the structure are:
__tests__
contexts
constants
helpers
hooks
stories
Why index.ts
To make it even simpler for engineers to find what they need, we use index.ts
as an entry-point to the component while having a named file for the actual implementation.
// without index.ts
import { Button } from "@common/Button/Button";
// with index.ts
import { Button } from "@common/Button";
Weakness
Like any other directory structure, it's not perfect. This directory structure is opinionated in a sense that your team needs to decide on what you would consider as a feature. For example, is User
different from UserProfile
? Can UserProfile
live under User
.
Another weakness that people might not like is how nested the directories can be.
Conclusion
This directory structure is meant to have a semantic way to structure your application. It's not meant to be a be-all and end-all solution. It's simply a solution that had made sense and worked for me.
If you liked certain aspects of this directory, and would like to adopt them; let me know in the comments on how you plan on adopting it. If you didn't like it or have suggestions on how to improve it, let me know in the comments.
Top comments (0)