How to setup your react applications
Tags: react, javascript, webdev, testing
Published: 2021-09-22 16:05:37

There is no right or wrong way when creating a React application. Being a library react doesn't have any predefined structure for an application, it gives us a lot of freedom to do things. Most of the time what people tend to do is create a `components` folder and use that as a place to store your complete application, this is not very scalable solution and the code becomes difficult to test or add features to. I like to keep my code structure in a way so that they are easy to test, being very obvious which makes adding features easy.

I am going to show you a way in which you can create a scalable architecture for a production React applications.

## Tech Stack
Following are the technologies I generally use while creating a production ready scalable react application:

- React with Hooks
- [Redux](https://redux.js.org/) for state management
- [React Router](https://reactrouter.com)
- [CSS Modules](https://github.com/css-modules/css-modules) or [Sass/Scss](https://sass-lang.com)
- [Jest](https://jestjs.io/) and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/)

## Build tools and Linting

I generally use [Create React App](https://create-react-app.dev/) for bootstrapping my react application, and add some custom configuration using [craco](https://github.com/gsoft-inc/craco) (**C**reate **R**eact **A**pp **C**onfiguration **O**verride).  

When a react application grows in size and complexity various problems also arise, managing imports is one of them. Aliases just makes importing from anywhere inside the project easy, also moving files is a very less hassle, you can easily do something like `import Component from @components/my-component`.

You can set up craco in you project and add the following to `craco.config.js` to enable aliases:

```js
const path = require("path");
module.exports = {
  webpack: {
    alias: {
      '@components': path.resolve(__dirname, "src/components/"),
      '@images': path.resolve(__dirname, "src/assets/images/")
    }
  }
}
```

Even your IDE can be set up to use these while auto-importing components/files.

As Create React App getting started template already comes bundled with [eslint](https://eslint.org/) I tend to leave the linting to it, and only add custom configurations if required to the eslint config file, or else we are good to go.

## Directory Structure

Following are the top level folders:

- assets - place to keep all your static assets from images, logos, splash, etc.
- components - shared/reusable components, like buttons, form components(select, input...), layout wrappers
- libs - for javascript modules, and also for custom hooks
- store - global redux store
- utils - utilities, helper methods
- pages - to store all the main views for our app, most of the app is contained here
- contexts - it is optional, but is used to store all the contexts used globally

```
└── /src
    ├── App.js
    ├── /assets
    ├── /components
    ├── /contexts
    ├── index.js
    ├── /libs
    ├── /pages
    ├── /store
    └── /utils
```

Apart from these, you can also add `types` if using react with typescript, but keep in mind these are a bit flexible, like `pages` can be called `views`, also you can separate javscript modules and hooks in two different directories.

## Components

All the shared components across the projects are stored here, also further grouping is done by type for example - `forms`, `layout`, etc.

Components have a single `component.js` file with named exports, its better to avoid default exporting which might create file name conflicts. Most of the times we are trying to create our own form system or layout from bindings from different libraries like Formik and Material UI, or ant design. So, I prefer to keep the files together in a folder so its easy to find them and work with them. Following is in a way I create files for a component:

- **Component.js** - Your React component goes here
- **component.module.css/component.scss** - All the styles related to this component

Here we have one thing to consider, you can either create a test file here or create a similar structure in your `__tests__` folder like following:

```
└── __tests__
    └── Components
        └── Component.test.js
```

Or, As I prefer them to be together in the `Components` folder itself with the `Component`  just makes them easier to find and concentrate on them.

- **Component.test.js** - tests cases related to your component

```
└── components
    ├── layout
    |   └── container
    │       ├── Container.js
    │       ├── container.scss
    │       └── Container.test.js
    └── navigation
        ├── NotFound
        │   ├── NotFound.js
        │   └── NotFound.test.js
        ├── PvtRoute
        │   ├── PvtRoute.js
        │   └── PvtRoute.test.js
        ├── RootNavigator.js
        └── RootNavigator.test.js
```

## Libs

This directory will host all our javascript modules/services which will be used throughout our application. Not only that but all our custom hooks can also be stored inside this directory. Following can be the way to setup the folder:

```
└── src
    └── libs
        ├── localStorage.js
        ├── useAuthentication.js
        └── useUser.js
```


## Store

This contains our global store, for our case it will be Redux. We will have folders for each of our features which will contain the reducers, actions and as well as tests. We will also have one `index.js` file which will be our `rootReducer`, which will be on the top most level of the store folder. The files can be created in the following manner:

```
└── src
    └── store
        ├── index.js
        ├── recipes
        │   ├── recipesAction.js
        │   └── recipesReducer.js
        └── user
            ├── userAction.js
            └── userReducer.js
```

It is very extensible method can can be used with [Redux Toolkit](https://redux-toolkit.js.org/) or with [Redux Sagas](https://redux-saga.js.org/), in place of `reducers` and `action` keywords it could be `slices` or `sagas`.

## Utils

Here we will store all our utilities, which will be used by the entire application. Not all code bases need a utils folder, but I recommend to have one to store all the global configurations and methods which can be used elsewhere in the app. It can contain a `helpers.js` file which can store all the different functions used. Another for form validation we can create, `validations.js`, and to store constants we can have one `constants.js`

```
└── src
    └── utils
        ├── constants.js
        ├── helpers.js
        └── validations.js
```

## Pages or Views

Here lives are our main chunk of the application, it can also be called `views` as each page is like a "view" in an application.  Anything inside a view is a page which will be used in a specific view - `AddRecipe` page which will only be used in context to `/recipes` route, and `UserProfile` page will only be used on the `/users` route.

The main advantage of storing our pages in this way, instead putting all of the pages together inside `components` or `pages` is that it makes it very easy to understand the app structure. If there are nested routes, you can always add a nested views folder within the main route.

```
└── src
    └── pages
        └── Recipes
            └── AddRecipe
                ├── AddRecipe.js
                └── AddRecipe.test.js
```

## Conclusion

This is my personal preference to setup a react based project/webapp, which scales when the code base becomes huge in production and its hard to manage resources. 

Would love to know more, how do you guys setup your react applications?