Best Practice To Manage Folder Structure For React.js

image.png

If you are reading this, you probably know what React.js is and might have already used it Earlier. However, you might be wondering why I am reading about folder structure?

Can’t I just stuff all my files in the src folder?? 🤪

Technically you could do that and React.js will take care of everything. But as soon as your project becomes larger, it will become hard for you to maintain your files and debug them. Also if you are going to work in a team with your team members, it's very difficult to grasp your code.

So there must be a perfect folder structure to keep your src folder clean.

React is all about Components!

Components are like JavaScript functions. Every application which we will develop in react will be made up of pieces called components. Components make the task of building UIs much easier.

Actually, entire UIs broke down into multiple individual pieces that are components and then work on them independently and merge them all into a parent component which will be the final UI.

In this section, we will cover only the directory structure of the React.js application.

So let's begin..... 🤩

Open your terminal

React Installation

Run the code

npm i -g create-react-app

npx create-react-app my-app-name

This will create a template React.js app that we can modify to make it our own.

After installing react node_modules will be automatically installed as shown below.

image.png

So, first, you need to de-structure it and delete some unwanted files/folders as we won't use all files or sections of code created by the template.

Delete all of these files:

  • All files in the /src directory except app.js, index.js, index.css
  • We can delete all the commented lines in index.html.
  • Delete all code inside return.

Finally, these files and folders are needed as given below.

image.png

Now let me explain the react folder structure which I’m following to develop a new application.

image.png

node_modules

  • node_modules folder is the repository of modules/libraries which you are using inside your project.

public

  • It contains static files such as index.html, JavaScript library files, images, and other assets.

src/components

  • It contains reusable components that are most often used to compose Feature or Page components.

src/assets

  • As the name suggests, all the static assets should reside here.
  • It contains the assets like images, CSS & fonts.
  • All assets will be accessible and imported from ‘/assets’.

src/layouts

  • It contains the layout components. A Layout Component is a component that composes the layout of a page like app_navbar, app_footer, etc.
  • If we don't use layout then we need to write code like for the navbar, header, footer, component whenever requires.
  • But if your project is likely to only have a single layout, this directory might not be necessary.

src/pages

  • It contains the page components and Each page component is associated with a route.
  • Page Components compose the content of a page by importing Components and Feature Components.

src/redux

  • It contains the redux files like actions, reducers, middleware, stores.
  • redux/actions: contains the action files. It is used to trigger action to update the redux state.
  • redux/middleware: When an action is dispatched, the action goes to middleware and executes the appropriate middleware. (we can perform async operations here)
  • redux/reducers: It contains the reducers files, each file will have a default export of function and will have various switch cases to update the redux state.

src/styles

  • It contains reusable global styles and themes.

src/app.js

  • App Component is the main component in React which acts as a container for all other components

src/index.js

  • It contains a method to render the application into real dom.
  • ReactDom is imported to render our entire react component in one particular div.

src/routes

  • It contains the page routes
  • To render a single component, wrap all the routes inside the Routes Component.
  • like:
<Routes>
    <Route exact path='/' element={< Home />}></Route>
    <Route exact path='/about' element={< About />}></Route>
    <Route exact path='/contact' element={< Contact />}></Route>
</Routes>

Note: By default, routes are inclusive which means more than one Route component can match the URL path and render at the same time. If we want to render a single component, we need to use Routes.

  • The Routes component in v6 effectively replaced the Switch component from v5.
  • the react-router new version is v6.2.1

Since version 6 is completely different from version 5 and uses Routes instead of Switches

I will explain this with the help of an example:- V5 code example:

    './src/app.js'// This is a React Router v5 app
    import {
      BrowserRouter,
      Switch,
      Route,
      Link,
    } from "react-router-dom";

    function App() {
      return (
        <BrowserRouter>
          <Switch>
            <Route exact path="/">
              <Home />
            </Route>
            <Route path="/about">
              <About />
            </Route>
          </Switch>
        </BrowserRouter>
      );
    }

This is the same app in v6:

'./src/app.js'// This is a React Router v6 app
import {
  BrowserRouter,
  Routes,
  Route,
  Link
} from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <Routes>                  // use Routes instead of Switches
        <Route path="/">        // Every path is exact in v6
              <Home />
          </Route>
         <Route path="/about">
              <About />
          </Route>
      </Routes>
    </BrowserRouter>
  );
}

The above example shows the basic structure of react-router.

But if we build a larger application, in that case, we need to follow a basic folder structure.

Let’s suppose you are going to build an application with react and firebase which does everything that’s needed to register, login, and logout users.

Set up everything to create a template Reactjs app.

npm i -g create-react-app
npx create-react-app react-firebase-authentication

image.png

You can consolidate all the routes of your application in a well-defined ‘src/constants/routes.js’ constants file shown below.

'src/constants/routes.js' 
export const SIGN_UP = '/signup';
export const SIGN_IN = '/signin';
export const HOME = '/home';
export const ACCOUNT = '/account';
export const ADMIN = '/admin';
export const PASSWORD_FORGET = '/pw-forget';

Each route represents a page in your application. For instance, the sign-up page should be reachable in development mode via localhost:3000/signup and production mode via yourdomain/signup.

  • Now, all these routes need to be accessible to the user. First, you need a router for your web application, which is responsible to map routes to React components. React Router is a popular package to enable routing, so install it on the command line:
  • npm install react-router-dom
  • The best way to start is by implementing a Navigation component that will be used in the App component. The App component is the perfect place to render the Navigation component because it always renders the Navigation component but replaces the other components (pages) based on the routes.
  • First the App component will use the Navigation component so implement that:-
'.src/app.js'
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import Navigation from '../Navigation';
const App = () => (
<Router>
<Navigation />
</Router>
);
export default App;
  • Second, implement the Navigation component. It uses the Link component of React Router to enable navigation to different routes. These routes were defined previously in your constants file.
  • Let’s import all of them and give every ink component a specific route.
'.src/components/navigation/index.js'
import React from 'react';
import { Link } from 'react-router-dom';
import * as ROUTES from '../../constants/routes';
const Navigation = () => (
<div>
<ul>
<li>
<Link to={ROUTES.SIGN_IN}>Sign In</Link>
</li>
<li>
<Link to={ROUTES.HOME}>Home</Link>
</li>
<li>
<Link to={ROUTES.ACCOUNT}>Account</Link>
</li>
<li>
<Link to={ROUTES.ADMIN}>Admin</Link>
</li>
</ul>
</div>
);
export default Navigation;

Now, run your application again and verify that the links show up in your browser and the URL also changes.

Notice that even though the URL changes, the displayed content doesn’t change. WHY???

Because here navigation is only there to enable navigation through your application, but no one knows what to render on each route.

Here the route to component mapping plays a role.

How to resolve??

See in our App component, we can specify which components should show up according to corresponding routes with the help of the Route component from React Router.

Open App component

'.src/app.js'
import React from 'react';
import {
BrowserRouter as Router,
Route,
} from 'react-router-dom';
import Navigation from '../Navigation';
import SignUpPage from '../SignUp';
import SignInPage from '../SignIn';
import PasswordForgetPage from '../PasswordForget';
import HomePage from '../Home';
import AccountPage from '../Account';
import AdminPage from '../Admin';
import * as ROUTES from '../../constants/routes';
const App = () => (
<Router>
<div>
<Navigation />
<hr />
<Route path={ROUTES.SIGN_UP} component={SignUpPage} />
<Route path={ROUTES.SIGN_IN} component={SignInPage} />
<Route path={ROUTES.PASSWORD_FORGET} component={PasswordForgetPage} />
<Route path={ROUTES.HOME} component={HomePage} />
<Route path={ROUTES.ACCOUNT} component={AccountPage} />
<Route path={ROUTES.ADMIN} component={AdminPage} />
</div>
</Router>
);
export default App;

Now if a route matches a path prop, the respective component will be displayed and thus, all the page components in the App component are exchangeable by changing the route.

This is how we enable a static frame with various components (e.g. Navigation) around our dynamic pages driven by routes.

src/service

  • Services are to manage all API requests.
  • It contains the dynamic HTTP request function using Axios.
  • All data requests are defined here, and response data is transformed and served. In some cases, it can also be saved in the redux store, i.e the middleware component will take care of everything.