visit
As React is just a lib, it doesn’t dictate rules about how you should organize and structure your projects. This is nice, because it gives us freedom to try different approaches and adapt the ones that better fit for us. On the other hand, this could cause some confusion for devs that are starting in React world.
In this post, I’m going to show some approaches that I have been using for a while and have been scaling very well. These approaches doesn’t re-create the wheel, they just put together and refine what we have on the market.Remember: Nothing here is written in rocks! You can take only the approaches you think that make sense and adapt/change it to fit in your context.
One of the questions I often see is regarding to how structure files and folders. In this post, we are considering you have a minimum structure, as the one created with create-react-app
.
The create-react-app
generates a basic project for us, containing in its root, the files: .gitignore, package.json, README.md, yarn.lock
It also generates the folders: public
and src
. The last one is where we keep our source code.
In this post, we are going to focus on src
folder. Everything that is outside that, will remain intact.
It’s likely that you already seen the separation between Containers and Presentation Components in the some project’s root folder. I mean, inside src
, you have a folder named components
and another folder named containers
:
src├─ components
However, this kind of approach has some issues, as you can see below:
components
to containers
folder and vice-versa.src└─ User ├─ components └─ containers
The above approach, minimize the problem about navigating between distant folders in the project tree. However, it adds a lot of noise. Depending on how many modules your application has, you would end up with dozens of containers
and components
folders.
For those reasons, when we are talking about organizing folders and files, it’s irrelevant to split our components by the concept of presentational vs container. That said_,_ we are going to keep all our components inside the components
folder, except the screens.
Even being irrelevant to separate them in folders, it’s important to know the conceptual difference between one and other. If you still have questions about this subject, I suggest you to read the article:
Inside the components
folder, we group the files by module/feature.
src└─ components └─ User
When a component is composed by more than one file, we put this component and its files in a folder with the same name. Eg: Let’s say you have a Form.css containing the Form.jsx’s styles. In this case, your structure would be like that:
src└─ components └─ User ├─ Form │ ├─ Form.jsx │
The test files stay with the file that is being tested. In the above case, the test for Form.jsx would stay in its same folder and would be named as Form.spec.jsx
Beyond separating the components by modules, we also include a UI
folder inside src/components
, to keep all our generic components in it.
When we talk about naming a component, it’s regarding to the name we give to the class or to the const that defines the component:
As mentioned before, the name we give to the components, should be clear and unique in the application, in order to make them being easier to find and to avoid possible confusions.
class MyComponent extends Component {}const MyComponent () => {};
A component’s name is very handy when we need to debug using tools as React Dev Tools, and when run time errors happen in the application. The error always come with the component name where it happened.
To name the components, we follow the pattern path-based-component-naming, which consists in naming the component accordingly to its relative path to the folders components
or to src
, in the case you are outside components
folder. Basically, a component that is located at: components/User/List.jsx
would be named as UserList
.
When the file is inside a folder with same name, we don’t need to repeat the name. That said, components/User/Form/Form.jsx
, would be named as UserForm
and not as UserFormForm
.
If you editor has support to fuzzy search, just searching for the name UserForm
would make you find the correct file:
If you want to search the file on the folder tree, you can easily find it just orienting yourself by the component name:
Following the pattern, you will always name the file accordingly to its context. Considering the above form, we know it is a user form, but as we are already inside the User folder, we don’t need to repeat that word in the component file name. So, we name it only as Form.jsx
When I started working with React, I used to put the full name in the file. However, that makes you repeat a name a lot of times and the importation path becomes too big. Take a look at the difference between the approaches:
import ScreensUserForm from './screens/User/UserForm';// vsimport ScreensUserForm from './screens/User/Form';
In the above example, you can’t see the advantage from one approach to other. But the application growing a little, it’s possible to see the difference. Take a look in the example below, considering a component from the project that I work on: import MediaPlanViewChannel from '/MediaPlan/MediaPlanView/MediaPlanViewChannel.jsx'; // vs import MediaPlanViewChannel from './MediaPlan/View/Channel'; Now imagine this multiplied by 5 or 10 times in a single file.For that reasons, we always name the file accordingly to its context and the component accordingly to its relative location to components
or src
folder.
In a CRUD of users, we would have a screen for the user list, a screen for create a new user and a screen for edit an existent user.
A screen is where you use components to compose a page to the application. Ideally, the screen would’t contain any logic and would be a functional component.We keep the screens in a separated folder in the root of src
, because they will be grouped accordingly to the route definition and not by modules:
src├─ components
Considering that the project is using react-router, we keep the file Root.jsx inside the screens
folder, and we define in it all the application routes.
The code for Root.jsx would be similar to this:
Notice that we put all the screens inside a folder with the same name of the route, user/ -> User/
. Try to keep a folder for each parent route, and group the sub-routes in it. In this case, we created the folder User
and we keep the screens List and screen Form in it. This pattern will help you find easily which screen is rendering each route, by just taking a look at the url.
You may notice that all the components contain the Screen as a prefix in it’s name. When the component is located outside the components
folder, we should name it accordingly to its relative path to src
folder. A component located at src/screens/User/List.jsx
should be named as ScreensUserList
.
With the Root.jsx created, our structure would be the following:
src├─ components
Don’t forget to import Root.jsx inside index.js to be the application root component.In case you still have a doubt about how a screen should look like, take a look at the example below, for what would be the screen for the user form.
Finally, our application would be structured like that:
src├─ components
src/**components**
src/**components**/**UI**
/user/list
we would have a screen located at /src/screens/User/List.jsx
.components
or src
. Given that, a component located at src/components/User/List.jsx
would be named as UserList
. A component located at src/screens/User/List
would be named as ScreensUserList
.src/components/User/List/List.jsx
would be named as UserList
and NOT as UserListList
.The above tips cover only a piece from organization and structure of a project. I tried to keep it only about React and leave Redux for a future post.
How about you? Do you have some approach that you would like to share with us? Write an answer below, I would love to read that! Did you enjoy the read? Help us spread the word by giving a like and sharing️️️️ ❤️️ Don’t forget to follow me, to receive notifications about future posts!