React 101: Directory Structure
Tags: react, architecture, beginners
Published: 2022-09-25 19:40:27

## 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.

```javascript
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.

```javascript
// 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.

## References

https://reactjs.org/docs/faq-structure.html