DEV Community

faraz ahmad
faraz ahmad

Posted on • Updated on

Opinionated React: Folder Structure & File Naming

Intro

I've been working with React for over 4 years. During this time, I've formed some opinions on how I think applications should be. This is part 1 in a collection of those opinions.

Folder Structure & File Naming

I have gone through many iterations of folder structure in the applications that I worked on. The one that I have found scales the best is to have flat folders and long file names. Since I use VSCode, it is easy to search for files, so the longer the name, the better. Here's how I layout most of my React applications.

Folder Structure

/react-app
  /build
  /node_modules
  /public
  /src
    /assets
    /components
    /contexts
    /lib
    /pages
    /services
    /styles
    AppRoutes.tsx
    index.tsx
    react-app-env.d.ts

  package.json
  README.md
  tsconfig.json
  yarn.lock
Enter fullscreen mode Exit fullscreen mode

Here's a quick overview of what are in these folders.

  • /assets - images, logos.
  • /components - components that are shared between multiple pages.
  • /contexts - I keep all of the context components in a separate folder, to not confuse them with plain old react components. A common context I like to implement is UserAuthContext.tsx.
  • /lib - When using a 3rd party library, let's say like Firebase for example, I like to put all of the initialization in a folder called lib. I'll then export the instance of that initialized library.
import firebase from "firebase/app";
firebase.initializeApp({
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  appId: process.env.REACT_APP_FIREBASE_APP_ID
});
export default firebase;
Enter fullscreen mode Exit fullscreen mode
  • /pages - Pages are also react components, but they represent a page or screen of an app. These map 1:1 with a route in the AppRoutes.tsx file.

  • /services - All of my api methods are put in a folder called services. I like to do this so that I don't put the business logic of an API call directly into a component, and so that any component can easily reference a service that it needs.

  • /styles - I very rarely write custom css, instead opting to use a framework like tailwindcss. This styles folder is where my generated styles and any custom css goes.

  • AppRoutes - This file contains all the routes of my application. I've been using react-router for a while, and I like to have one file that contains all my routes so that I can see it all at a glance.

import React from "react";
import { Switch, BrowserRouter, Route } from "react-router-dom";
import { useAuthContext } from "./contexts/AuthContext";
import { Navbar } from "./components/Navbar";
import { LandingPage } from "./pages/LandingPage";
import { DashboardPage } from "./pages/DashboardPage";

export const AppRoutes: React.FC = () => {
  const authAccount = useAuthContext();

  return (
    <BrowserRouter>
      <div className="mt-8 w-4/5 max-w-6xl m-auto">
        <Navbar />
      </div>
      <Switch>
        {authAccount ? (
          <AuthenticatedAppRoutes />
        ) : (
          <UnauthenticatedAppRoutes />
        )}
      </Switch>
    </BrowserRouter>
  );
};

const UnauthenticatedAppRoutes: React.FC = () => {
  return (
    <React.Fragment>
      <Route exact path="/" component={LandingPage} />
    </React.Fragment>
  );
};

const AuthenticatedAppRoutes: React.FC = () => {
  return (
    <React.Fragment>
      <Route exact path="/" component={DashboardPage} />
    </React.Fragment>
  );
};
Enter fullscreen mode Exit fullscreen mode
  • index.tsx - This is your typical index file, where you render your React app to the document.

File Naming

My rule of thumb is the longer and more descriptive the file name, the better. For files that that export React components I use PascalCase, for everything else I use dash-case.

# PascalCase
/components/NavBar.tsx
/contexts/UserAuthContext.tsx
/pages/DashboardPage.tsx
# dash-case
/services/auth-service.ts
/lib/apollo-client.ts
Enter fullscreen mode Exit fullscreen mode

I always prefer named exports instead of default exports. This makes it easier to search what I'm looking for in my editor.

Updates

I received some questions about this post, here are my responses:

Would be very interesting to see the structure inside of /components. Is there any nesting? A folder for each component with styles/test/... next to the component file itself?

I don't use any nesting in any of the folders. I also typically don't have a separate styles file, since I use frameworks like tailwind or bootstrap. The shape of of my components folder is like so:

/components
  /__tests__
    Button.test.tsx
Button.tsx
Enter fullscreen mode Exit fullscreen mode

What do you do with one-off components? For example, a Contacts.jsx page has a ContactList component?

I will split up my page into sub-components, all within the same file as the page.

import * as React from 'react'

export const ContactsPage: React.FC = () => {
  return (
    <div>
      <h1>Contacts</h1>
      <ContactsList />
    </div>
  )
}

const ContactsList: React.FC = () => { ... }
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

This is the first post in a series of posts I will be doing. If you enjoyed this, please give me some hearts and leave a comment below. What else would you

As always, I'm open to recommendations.

Thanks for reading.

Top comments (16)

Collapse
 
jkhaui profile image
Jordy Lee

Great template, I follow something similar. The one thing that annoys me when looking up react projects on GitHub is they all use different directory structures.
This is one area I wish react was more opinionated about, even if it just involved recommended guidelines for project structure

Collapse
 
farazamiruddin profile image
faraz ahmad

It took me a long time to land on this. I tried several different styles, but this is the one that has worked the best for me thus far.

Collapse
 
jannikwempe profile image
Jannik Wempe

Interesting...
I have a similar approach. Would be very interesting to see the structure inside of /components. Is there any nesting? A folder for each component with styles/test/... next to the component file itself? A single index.ts to re-export all components? Or a index.tsx in every components folder?

As you can see, I think there are many different approaches to the /components folder. Would love a followup article or edit on that.

Do you have any project where you applied that structure, that you can share? Would be interested in some API files.

Thanks :)

Collapse
 
farazamiruddin profile image
faraz ahmad • Edited

I don't use any nesting in any of the folders. The shape of of my components folder is like so:

/components
  /__tests__
    Button.test.tsx
Button.tsx

I usually don’t have styles files in my apps. I use plain css frameworks like tailwind or bootstrap so there is not a separate styles file.

Collapse
 
connerthebush profile image
Conner Bush • Edited

I see you have /components for shared components and /pages for the exact page matches, but what do you do with one-off components? For example, a Contacts.jsx page has a ContactList component. It’s not a shared component, but it’s not a page, either. I suppose in this design those components either are flattened into the one page component or live as a separate component but in the same file as the page. Is that correct?

Collapse
 
farazamiruddin profile image
faraz ahmad

That's correct! I will split up my page into sub-components, all within the same file as the page.

import * as React from 'react'

export const ContactsPage: React.FC = () => {
  return (
    <div>
      <h1>Contacts</h1>
      <ContactsList />
    </div>
  )
}

const ContactsList: React.FC = () => { ... }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
vincevegas profile image
vince vegas

What if the component item does have a third-party library attach to it
eg.

import React from 'react';
import Zoom from 'react-reveal/Zoom';

const movieCard = () => (

....content

)

Is this the right structure if one component has some functionality on it

Collapse
 
anuraghazra profile image
Anurag Hazra

Hey great article, I wanted to ask you, how do you structure your graphql related files (client, queries, mutations, generated code)

Collapse
 
farazamiruddin profile image
faraz ahmad

I like to write my GraphQL queries and mutations in-line within the component file, since my queries are almost always 1:1 with the component that is using it. You can see this here: dev.to/farazamiruddin/an-opinionat...

As far as generated code, I keep a top level folder for all generated code and title it __generated__. All the auto-generated type definitions go in there.

Collapse
 
felipetomazec profile image
Felipe Tomaz

Awesome articles, man!

Collapse
 
farazamiruddin profile image
faraz ahmad

Thank you! I appreciate it 🙏🏽

Collapse
 
aubreyhbarkun profile image
aubrey

Can't tell you how much I appreciate this. Simple, concise. Well done.

Collapse
 
hanuz06 profile image
Andrey Li • Edited

Thank you Faraz. I started a new project and follow your folder structure. I wonder how do you use AppRoutes.tsx? Is it just used in App.tsx like <AppRoutes/>.

Collapse
 
neuhaus93 profile image
Lucas Arendt Neuhaus

What about custom hooks? Does it go on services?
Really liked the template, but that's one thing I would have in mine (a hooks/ folder).

Collapse
 
nuwannnz profile image
Nuwan Karunarathna

Interesting article! btw I have a question. Where do you put the files related to Redux like the actions and redcuers?

Collapse
 
farazamiruddin profile image
faraz ahmad

Thank you! I don't use redux, but if I did (or any other state management library for that matter), I would follow the same principle; flat folders, long file names.

/src
  /actions
    user-actions.ts
    movie-actions.ts
  /components
    MovieList.tsx
  /reducers
    user-reducer.ts
    movie-reducer.ts