Skip to content

React JS Folder Structure

Spinning Idea edited this page Aug 2, 2022 · 20 revisions

React JS Application Folder structure

There are a number of approaches to structuring the folders within a React JS application. Below is one approach that allows clear convention and organization.

Architecture

Pages

Pages are the top level components that are routed to by the main router. They are components themselves that leverage other components to compose the page and work surface as a whole. Pages form the primary building block of an application and differently from the other components, are very strictly scoped (and own specific URL path similar to an API controller owning a route segment). Instead of having a single page application this approach breaks apart the application into an "MPA" or Many Page Application.

Example:

pages
├── home.tsx
├── about.tsx
├── signin.tsx

For the home and about it's fairly simple, a page is supposed to be the result of the composition of other components, which have proper tests, so create a specific directory for them.

The case is different for the sign in page, which has something specific, a sign-form component. In this case, I use the approach of creating a nested component folder.

This approach is powerful because lets you split the code into small chunks, but keeps the architecture well organized. The signin-form component should be put into the "main" components folder. If the application grows, and the signin-form component will be used in several pages, nothing prevents you from moving it to common.

Another tip I usually suggest is to keep a consistent name between the page and the route, something like this:

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="about" element={<About />} />
  <Route path="sign-in" element={<SignIn />} />
</Routes>

Components

Components folder contains all the components that are used more than one single time in the app including every feature-specific component.

Create subfolders to differentiate between application, page, and common or shared reusable logic. A button is supposed to be used on almost every page of our app, so that goes into "common" directory. The signup-form component is page specific so that goes into a subfolder with that page name.

Suppose you have two different pages for sign-in and sign-up, this component needs to be repeated two times, that’s the reason why is put into the components folder but as a scoped into subfolders by page name within components.

Examples:

common

├── components
│   ├── common
│   │   └── button
│   │       ├── button.tsx
│   │       ├── button.stories.tsx
│   │       ├── button.spec.tsx
│   └── signup
│       ├── signup-form.tsx
│       ├── signup-form.spec.tsx
│   └── home
│   │       ├── getstarted.tsx
│   │       ├── getstarted.spec.tsx

Some examples of what can be inserted into the common folder:

Notice also that every single component is placed into a proper directory with a very easy-to-understand naming convention.

button
├── button.tsx
├── button.stories.tsx
├── button.spec.tsx
└── index.ts

That’s because your app can eventually contain dozens of components, and if all of them have a test or a storybook file, this can easily become messy.

Let’s explore some key points of this folder:

  • All the component-related files are in this folder.
  • All the exportable modules are put into an index.ts to avoid double name in import.
  • All the files are named in kebab-case.

Questions:

  • Where is the button component? -> In the button folder.
  • Where are the stories for this button? -> In the button folder.

Layouts

Layouts are not pages but rather they are components that layout the application page structure to include menuing and header, footer. If need arises for different layouts you can put them all in this folder.

Example:

layout
├── main.tsx
└── auth.tsx

One thing you may notice is the name is not main-layout.tsx but just main, that's because following this reason you would have to rename all the components like table-component.tsx which is weird. So I name all the components without the obvious suffix given by the parent directory, and if I need to underline that I'm using a layout I can always use an import alias as well.

import { Main as MainLayout } from "@/layouts/main.tsx";

Contexts, Hooks & Stores

Use kebab-case lower case for all the filenames:

Examples:

hooks
├── use-auth.ts
└── use-click-outside.ts
contexts
└── authentication.tsx
hooks
├── use-users
│   ├── use-users.ts
│   ├── use-users.spec.ts
│   └── index.ts
└── use-click-outside.ts

Utilities

Often the application and pages or components need shared functions for handling currency or dates or processing collections in javascript (eg formatCurrency function that properly formats and adds a dollar sign - put currency formatting in currency.ts and any date formatting in date.ts)

The utilities folder is the place to put these library functions.

Example

utilities
├── currency.ts
├── dates.ts
└── collections.ts

Also, put constants in a single file to encapsulate them into a specific file.

// @/constants/index.ts
export const SUPPORT_EMAILADDRESS = "support@email.com";
export const SUPPORT_USERNAME = "Support";

// And use them
import { SUPPORT_EMAILADDRESS , SUPPORT_USERNAME } from "@/constants";

Styles

Simply put global styles into a styles folder, and your game is done.

Example

Application

styles
├── index.css
├── colors.css
└── typography.css

Components

What about CSS for components?

button
├── button.tsx
├── button.stories.tsx
├── button.styled.tsx
├── button.module.scss
├── button.spec.tsx
└── index.ts

If you are using emotion, styled-components, or simply the CSS Modules, put them into the specific component folder, so everything will be optimally packaged.

Config Files

The config folder avoids root directory pollution with non-relevant files. The config folder should contain Application configuration files like Dockerfiles, Fargate Task Definitions, and so on.

See Also

Clone this wiki locally