• Structuring projects and Naming Components in React
  • Original author: Vinicius Dacal
  • Translation from: Aliyun Translation Group
  • Text link: github.com/dawn-teams/…
  • Translator: Also tree

React project structure and component naming

React, as a library, does not dictate how you structure your projects. This is a good thing, because it gives us the freedom to experiment with different ways of organizing and choose the one that works best for us. On the other hand, this can be a bit confusing for developers just getting started with React.

In this article I’m going to show you what I’ve been doing for a while and it works, not by reinventing the wheel, but by combining and refining solutions in the community.

Note: Nothing here is infallible! You can choose what you think is easy to understand and can be adapted or adapted to suit your situation.

The directory structure

One of the most common problems I see is how to organize files and directories. For the purposes of this article, we assume that you have the simplest directory structure created by create-react-app.

Create-react-app generates a basic project for us, including the root directory and files such as. Gitignore, package.json, readme. md, and yarn.lock.

It also generates the public and SRC directories, where we store the source code.

Take a look at the structure depicted in the following image:

In this article we will focus only on the SRC directory; everything outside it will remain the same.

Containers and Components

We can see that there are containers directories and components directories under the SRC directory:

SRC ├─ components ├─ containersCopy the code

But this approach can lead to the following problems:

  • Subjective rules You don’t know what a container is and what a component is, and the difference between the two is subjective. It’s very difficult to get all developers to agree and judge both equally if you push it across your team.
  • Component changes are not consideredEven if you decide that a component is suitable for a particular category, it can easily change over the life of the project, eventually forcing you to remove it fromcomponentsMoved tocontainersDirectory and vice versa.
  • The naming of components in an application should be declarative and unique to avoid confusion about the responsibilities of components with the same name. But the above approach opens the way for two components to have the same name, one can be a container and the other can be a presentation component.
  • Inefficiencies Even when you are implementing a standalone feature, you often have to switch back and forth between the containers and Components directories, because it is quite normal for a standalone feature to have two different types of components.

A variant of this approach keeps the two directories separate in the module’s directory.

Imagine having a User module in your application. Under this module, you have two directories to separate your components:

SRC ├─ User ├─ components ├─ containersCopy the code

This minimizes the problem of constantly switching between two remote directories, but it also adds a lot of annoyance. When your application has a very large number of modules, you can end up creating dozens of containers and Components directories.

So when we talk about how directories and files are organized, it doesn’t matter whether components are split into presentation and container types. That is, we will put all the components in the Components directory except the page.

Even if splitting them in a directory is not necessary, it is still necessary to understand the differences between them. If you still have questions on this topic, you are advised to read this article: Presentational and Container Components.

Split and combine code

In the Components directory, we organize files by module/feature structure.

In the process of adding, deleting, modifying, and checking users, we will only have one User module. So our directory structure would look like this:

SRC ├─ ├─ ├─ list.jsxCopy the code

Whenever a component has more than one file, we put the component and its corresponding file in the same folder and use the same name. For example, now that we have a form. CSS file that contains the form. JSX style, our directory structure will look like this:

SRC └ ─ components └ ─ User ├ ─ Form │ ├ ─ Form. The JSX │ └ ─ Form. The CSS └ ─ List. The JSXCopy the code

The test files are placed together with the files being tested. In this example, the form.jsx test files are placed in the same folder and named form.spec.jsx

UI components

In addition to splitting components by module, we also place a UI directory in SRC/Components for all common components.

UI components do not belong to any one module and need to be generic. They should be readily available in open source libraries because they do not contain any application-specific business logic. Common components are buttons, input boxes, check boxes, drop-down selection, modal boxes, data visualization components, and so on.

The component named

We’ve seen how to organize the directory structure and how to break up our components by modules, but there’s still a problem: how to name them?

Here we are talking about how to name our class or define component constants.

class MyComponent extends Component {}
const MyComponent = () => {};
Copy the code

Component names should be clear and unique in the application so that they can be easily found and avoid possible confusion.

The component name is handy when an application encounters an error at runtime or when debugging with the React developer tool, because the component name often accompanies the error.

We use path-based component naming, which is based on the path relative to the components file directory or, if outside this folder, the path relative to the SRC directory. For example, if the component’s path is components/User/ list.jsx, it will be named UserList.

If the file name is the same as the file directory name, we do not need to repeat the name. That is, the components/User/Form/Form JSX will be named the UserForm rather than UserFormForm.

Naming in this way has the following advantages:

Easy to search for files in your project

If your editor supports fuzzy search, simply search UserForm to find the corresponding file:

If you want to search for a file in the directory tree, you can easily locate it by the component’s name:

You can avoid repeating names in import

In this way, you can name files according to the context of the component. Consider the form component above. We know that it is a form component in the User module, but since we have placed the form component in the User module’s directory, we do not need to repeat the word User in the form component’s filename. Use form.jsx.

When I first used React, I liked to name files with full names, but this caused the same part to be repeated too many times and the import path to be too long. Take a look at the differences between the two approaches:

import ScreensUserForm from './screens/User/UserForm';
// vs
import ScreensUserForm from './screens/User/Form';
Copy the code

In the example above, we don’t see a clear advantage. But you’ll see the difference when your application gets a little more complicated. Let’s take a look at this example from my actual project:

import MediaPlanViewChannel from '/MediaPlan/MediaPlanView/MediaPlanViewChannel.jsx';
// vs
import MediaPlanViewChannel from './MediaPlan/View/Channel';
Copy the code

Now imagine repeating the same file name five to ten times.

For this reason, we think it is better to name the component file according to its context and its relative path.

Page (Screen)

If we want to add, delete, change and review a user, we need a user list page, a page to create a new user, and a page to edit an existing user.

In an application, the result is a page by combining components with each other. Ideally, the page should contain no logic, just a functional component.

We use the SRC directory as the root directory and split the different pages into different folders. Because they are grouped based on route definitions rather than modules.

SRC ├─ molecular Exercises ─ molecular Exercises ─ molecular ExercisesCopy the code

Assuming we are using the React-Router in our project, let’s place the root. JSX file under the Screens directory and define all the routes we apply there.

The code for root.jsx might look like this:

import React, { Component } from 'react';
import { Router } from 'react-router';
import { Redirect, Route, Switch } from 'react-router-dom';

import ScreensUserForm from './User/Form';
import ScreensUserList from './User/List';

const ScreensRoot = (a)= > (
  <Router>
    <Switch>
      <Route path="/user/list" component={ScreensUserList} />
      <Route path="/user/create" component={ScreensUserForm} />
      <Route path="/user/:id" component={ScreensUserForm} />
    </Switch>
  </Router>
);

export default ScreensRoot;
Copy the code

Notice that we put all the pages in the same directory, named after the route name. Try to create a directory for each parent route and organize the child routes in this directory. In this example, we create the User directory and place the List page and Form page inside. This way you can easily locate the page rendered by the current route just by looking at the URL.

As in the example above for creating and editing a user’s route, a page may be rendered by two different routes.

You may have noticed that all components prefix their names with Screen. When components are used outside the component directory, we need to name them with their path relative to the SRC directory. Located in the SRC/screens/User/List. JSX components should be named ScreensUserList.

Including root.jsx, our directory structure is as follows:

SRC ├ ─ components └ ─ screens ├ ─ User │ ├ ─ Form. The JSX │ └ ─ List. The JSX └ ─ Root. The JSXCopy the code

Don’t forget to include root.jsx in index.js as the Root component of your application.

If you have any questions about what a page looks like, take a look at the following example, which is a page for a user form.

import React from 'react';
import UserForm from '.. /.. /components/User/Form/Form';

const ScreensUserForm = ({ match: { params } }) = > (
  <div>
    <h1>{` ${! params.id ? 'Create' : 'Update'}`} User</h1>
    <UserForm id={params.id} />
  </div>
);

export default ScreensUserForm;
Copy the code

Eventually, our directory structure will look like this:

SRC ├─ exercises - ├─ User │ ├─ Form │ │ ├─ Form │ ├─ ├─ ├─ ├.jsx │ ├─ ├.jsxCopy the code

Review key points

  • The presentation and container components are placed in the SRC/Components directory
  • Components are organized by modules/features
  • The basic UI components are placed in the SRC/Components /UI directory
  • Keep the page simple and use the most concise structure and code
  • Organization pages are defined by routing. For routing address/user/list, we will have a page in the/SRC/screens/user/list. The JSX.
  • Components by the relative components or SRC path name, that is to say, in the SRC/components/User/List. The JSX position components will be named the UserList. In the SRC/screens/User/List. The component will be named ScreensUserList JSX position
  • When a component has the same name as a directory, do not repeat that name when using the component. Consider a scenario, in SRC/components/User/List/List JSX position components will be named the UserList rather than UserListList.