When we start to develop a project with a new language or framework, one of the first questions that arise is how I organize my project and, in the case of React, this is no exception.

If we rely on the official documentation, React does not define a correct way to organize our files and leaves it to the discretion of the developer. This may seem strange if we have previously worked with frameworks such as Angular, but we must bear in mind that React is a frontend library that can be used both to create complete applications, as well as for specific components within an existing code base.

However, they do offer a couple of examples of popularly used structures. These are the file type based structure and the feature based structure. Unfortunately, the variants they show fall short and don't cover even the simplest project.

In this article we are going to see 4 ways to organize and structure React and React Native projects and we will give our opinion about them.

Folder structures for React project

Structure based on file type

If you are starting to use React, it is most likely that you will start with an organization based on file type where most of the files are located inside folders with the name of each type and that are at the root level of our project.

This organization allows us to have a very simple structure for projects that are starting and it is the one that I would recommend for all those who start with React. The main problem is that once our project starts to grow, it can become a real chaos, especially at the component level, since in the simplest variant we would have them all inside a components folder.

That's why the version I like the most for this type of organization is the one that differentiates between components and pages. In this way, at the root level we would have a components folder for shared components, and in the pages folder each page would contain the main view and the components that are only used on that page. With this variation this structure scales much better and we can take it to much larger projects.

src/
|-- components/
|   |-- Avatar/
|   |   |-- Avatar.jsx
|   |   |-- Avatar.test.js
|   |-- Button/
|   |   |-- Button.jsx
|   |   |-- Button.test.js
|   |-- TextField/
|   |   |-- TextField.jsx
|   |   |-- TextField.test.js
|-- contexts/
|   |-- UserContext/
|   |   |-- UserContext.js
|-- hooks/
|   |-- useMediaQuery/
|   |   |-- useMediaQuery.js
|-- pages/
|   |-- UserProfile/
|   |   |-- components/
|   |   |   |-- SomeUserProfileComponent/
|   |   |   |   |-- SomeUserProfileComponent.jsx
|   |   |   |   |-- SomeUserProfileComponent.test.js
|   |   |-- UserProfile.jsx
|   |   |-- UserProfile.test.js
|   |-- index.js
|-- routes/
|   |-- routes.jsx
|   |-- routes.test.js
|-- utils/
|   |-- some-util/
|   |   |-- index.js
|   |   |-- someUtil.js
|   |   |-- index.test.js
|-- services/
|   |-- some-service/
|   |   |-- index.js/
|   |   |-- someService.js/
|   |   |-- index.test.js
|-- App.jsx
|-- index.js

As we can see in the example, this structure is very intuitive for anyone who reviews our code, that is why it is the organization that is most often used when starting with React.

Modular structure or feature based

The next method of organization mentioned in the documentation is the feature based one. This structure is interesting for projects with a larger scale.

The main idea is that each module we define has all the code related to it and only code from the module itself is imported. When we have several modules that need the same piece of code, we can write it into a shared folder and import it into the different modules. The fundamental rule to be followed is not to import code between modules.

src/
|-- components/
|   |-- Avatar/
|   |   |-- Avatar.jsx
|   |   |-- Avatar.test.js
|   |-- Button/
|   |   |-- Button.jsx
|   |   |-- Button.test.js
|   |-- TextField/
|   |   |-- TextField.jsx
|   |   |-- TextField.test.js
|-- contexts/
|   |-- UserContext/
|   |   |-- UserContext.js
|-- hooks/
|   |-- useMediaQuery/
|   |   |-- useMediaQuery.js
|-- features/
|   |-- Home/
|   |   |-- components/
|   |   |   |-- SomeUserProfileComponent/
|   |   |   |   |-- SomeUserProfileComponent.jsx
|   |   |   |   |-- SomeUserProfileComponent.test.js
|   |   |-- utils/
|   |   |-- services/
|   |   |-- hooks/
|   |   |-- contexts/
|   |   |-- views/
|   |   |   |-- HomeView.jsx
|   |   |-- pages/
|   |   |   |-- HomePage.jsx
|   |-- index.js
|-- utils/
|   |-- some-common-util/
|   |   |-- index.js/
|   |   |-- index.test.js
|-- services/
|   |-- some-common-service/
|   |   |-- index.js/
|   |   |-- some-common-service.js/
|   |   |-- index.test.js
|-- App.jsx
|-- index.js

The main ideas behind this method of organization are based on the concepts explained in Domain Driven Design applied for a long time in the backend. The great drawback of this structure is that it can be complex to define what a module is and this can has a great impact on the success of our organization.

Structure based on Atomic Design

Once the structures based on features and file type have been covered, another concept that often appears is that of Atomic Design. This is a methodology for creating design systems developed by Brad Frost and Dave Olsen and it is not unique to React, but it fits very well with the library due to the way of creating component-based interfaces.

Atomic Design is not a complete method of structuring our project, but a way of organizing our components. Therefore it would be more of a pattern that we can apply within our existing organization.

The main idea is to divide our components into five types of elements:

  • Atoms
  • Molecules
  • Organisms
  • Templates
  • Pages

If we apply this in the two structures that we have seen, they would look as follows:

File type based

src/
|-- components/
|	 |- atoms/
|  |  |-- Button/
|	 |  |   |-- Button.jsx
|	 |  |   |-- Button.test.js
|  |- molecules
|  |- organisms
|  |- templates
|-- contexts/
|   |-- UserContext/
|   |   |-- UserContext.js
|-- hooks/
|   |-- useMediaQuery/
|   |   |-- useMediaQuery.js
|-- pages/
|   |-- UserProfile/
|   |   |-- components/
|   |   |   |-- SomeUserProfileComponent/
|   |   |   |   |-- SomeUserProfileComponent.jsx
|   |   |   |   |-- SomeUserProfileComponent.test.js
|   |   |-- UserProfile.jsx
|   |   |-- UserProfile.test.js
|   |-- index.js
|-- routes/
|   |-- routes.jsx
|   |-- routes.test.js
|-- utils/
|   |-- some-util/
|   |   |-- index.js
|   |   |-- someUtil.js
|   |   |-- index.test.js
|-- services/
|   |-- some-service/
|   |   |-- index.js/
|   |   |-- someService.js/
|   |   |-- index.test.js
|-- App.jsx
|-- index.js

Feature based

src/
|-- components/
|	 |- atoms/
|  |  |-- Button/
|	 |  |   |-- Button.jsx
|	 |  |   |-- Button.test.js
|  |- molecules
|  |- organisms
|  |- templates
|-- contexts/
|   |-- UserContext/
|   |   |-- UserContext.js
|-- hooks/
|   |-- useMediaQuery/
|   |   |-- useMediaQuery.js
|-- features/
|   |-- Home/
|   |   |-- atoms/
|   |   |-- molecules/
|   |   |-- organisms/
|   |   |-- utils/
|   |   |-- services/
|   |   |-- hooks/
|   |   |-- contexts/
|   |   |-- pages/
|   |   |   |-- HomePage.jsx
|   |-- index.js
|-- utils/
|   |-- some-common-util/
|   |   |-- index.js/
|   |   |-- index.test.js
|-- services/
|   |-- some-common-service/
|   |   |-- index.js/
|   |   |-- some-common-service.js/
|   |   |-- index.test.js
|-- App.jsx
|-- index.js

The truth is that when I've had the chance to use Atomic Design in a React project, it has not convinced me. Personally, the main drawback is that you have to learn to categorize each type of element and this is fine if the whole team knows the methodology but otherwise it can create more problems than it solves.

Even so, if your team is used to working with this methodology or you are looking for a new way to organize the projects and you like the ideas described by Brad's method, it is a very good way not only to structure the code in our application, but even to structure our own design system in applications like Figma.

Structure based on hexagonal architecture

Finally, I would like to mention the structure based on the hexagonal architecture. This is the only one that I have not used at the moment but I find it very interesting, especially if the team is Full-Stack and is used to work with this architecture on the backend.

This is the most complex organization of all that we have seen and bases its ideas on the architecture developed by Alistair Cockburn. In this article we are only going to show an example of how look like applied to a React project, but there are a lot of resources out there to dig deeper.

src/
|-- domain/
|   |-- models/
|   |   |-- User.js/
|   |-- services/
|   |   |-- User.service.js/
|-- infrastructure/
|		|-- components/
|		|   |-- Avatar/
|		|   |   |-- Avatar.jsx
|		|   |   |-- Avatar.test.js
|		|	  |-- UserProfile/
|		|   |   |-- UserProfile.jsx
|		|   |   |-- UserProfile.test.js
|		|-- http/
|		|   |-- dto/
|		|   |   |-- userDto.js/
|		|   |-- http.js
|		|-- repositories/
|		|   |-- user.repository.js/
|-- App.jsx
|-- index.js

As we see at first glance, if we have never dealt with the hexagonal architecture it can be quite complex to understand where each part of our code is. I would only use this structure in case that we are used to work with it in our backend and we want to maintain the same architecture on the frontend. If not, I do believe that the ones we have seen in the previous points are more recommended for most projects.

Conclusions

As we can see there are many ways to organize our code from the simplest to the most complex. A simple way of organization does not have to be worse than a complex one, it all depends on the size of our code base and the size of the team that manages it.