Although I have successfully completed several React projects, I still do not have one the best directory structure. I think this is mainly because:
React and its ecosystem are constantly evolving.
Each team has people with different backgrounds.
Every application is different (yeah, I know, it's so obvious).
Therefore, I think there is such a thing as a perfect directory or file structure in a React application. Anyway, a very important sentence on this topic can also be found in the official React documentation:
If you’re just starting a project, don’t spend more than five minutes on choosing a file structure. Pick any of the above approaches (or come up with your own) and start writing code! You’ll likely want to rethink it anyway after you’ve written some real code.
However, looking through all my completed React projects, I can see that they have several common parts. Maybe for most of you they will be quite obvious but I'll list them below as they might help someone start their own React project.
Grouping by file type
This is one of the approaches that the React documentation mentions, and it certainly works best for me.
In this approach, we assume that the main elements of the application have their parent folders. And so, almost for sure, separate folders will have files such as:
pages (Next.js, Gatsby), views, scenes or containers
interfaces or types (when using TS)
Components are the basic elements from which applications in React are built. Personally, I prefer to start projects from one folder, common to all components. However, it is important that each component should have its own separate folder, as in the example below.
Each folder should contain files related only to a given component. Let's take, for example, the Header component. Inside the
Button folder, we should keep files such as:
Header.tsx (component file)
Header.test.tsx (component test file)
index.ts (optionally, a file to export the default component from the folder)
Using one folder for component I like to build components according to Composition Pattern. If I can break my component into smaller elements, then if they are only used by this one main component, I keep them together in one directory. Look at the example:
There is one more benefit of keeping components in separate folders. If their number becomes large and it is difficult for us to find the desired component, then we can use additional nesting of folders, e.g. by dividing them according to their type, functionality or their size. An example here can be the Atomic Design System, according to which components can be divided into: atoms, molecules, organisms, templates and pages. Of course, this division can be arbitrary and sometimes it is fair enough to divide the components into elements (single components) and modules (components build with multiple elements).
By pages, I mean those files that are directly related to route based on its filename, so each route in the application has its own page. This approach is used in Next.js applications. These files are of course nothing more than components that often combine the responsibility for applying the appropriate layout and fetching the data. Sometimes different names are used for pages: views, scenes or containers. Personally I prefer using pages or views.
Since pages usually have a similar layout, i.e. they use the same main elements as the header or footer, have specific widths, colors and other details, instead of duplicating them on each page, I like to create layout components. I store layout components in the
Layouts folder. These components are responsible only for the UI and wrap the content displayed on the page supplementing it with the necessary elements. Maybe this example below is a bit naive, but roughly that's what it's all about:
It seems obvious that it is good to keep all the methods responsible for fetching data from various sources in separate files, let's call them services, so they can be easily reused in different parts of the application. In the services folder I try to keep everything related to communication with the outside. But not only. Often there are services with different handlers for various types of files (e.g. json files) or pictures. Below I will show an example of services folder in one of my projects.
This one is easy. In React best practices we always keep an assets folder inside the
src which may contain images, icons and font files.
When using typescript, it seems necessary to have one place to hold all defined interfaces or new types created. It is often convenient to keep them directly where they are used, however, as they are often reused in different places, we should consider having a separate space for types and interfaces. Hence, whenever I write in typescript, I have one interfaces directory, where I collect all files of this type.
Sooner or later we will need space for various additional elements such as helper functions, custom hooks, configuration files or enums (typescript). Personally, I like to have one place where I keep such additional things. Sometimes it's called
commons. Of course, inside such a directory I do not throw everything as it goes, but I divide it into smaller directories. Thanks to this, I get a place that allows me to have a little mess. But at least I know that this is the place, and I often refactor it while working.
Anyway, I think that this is one of the most important things when working with a React application - we can never close ourselves to changes in the directory structure. We should not assume that it will be perfect from the very beginning. Remember that it usually develops during the project and this is something natural.
In addition to the directories listed above, you will probably need those related to state management, e.g. with reducers and actions (if you are using Redux), or stores (if you are using MobX) or for handling the global context.
If your application will be based on routing, you may also need a separate folder in which you will keep the entire routing configuration as well as grouped routes.
Finally, keep in mind what is written in the React documentation:
Don't overthink it
The final directory structure always evolves over the project and you shouldn't assume that you will do it right from the very beginning.