DEV Community

Cover image for Best Folder Structure for Scalable React Apps: A Complete Step-by-Step Guide

Best Folder Structure for Scalable React Apps: A Complete Step-by-Step Guide

🎯 Introduction

When working on a React project, organizing your files and folders effectively is crucial for scalability, maintainability, and team collaboration. A well-structured project helps developers navigate the codebase efficiently, reduces complexity, and promotes best practices. πŸ—οΈ

In this article, we will explore a scalable folder structure for React applications using TypeScript, styled-components, Redux, and Context API, considering modularisation, separation of concerns, and best coding practices. πŸ“

πŸ“‚ Basic Folder Structure

Folder structer
A modern React project using TypeScript, styled-components, Redux, and Context API follows this structure:

my-app/
β”œβ”€β”€ node_modules/
β”œβ”€β”€ public/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ App.tsx
β”‚   β”œβ”€β”€ index.tsx
β”‚   β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ assets/
β”‚   β”œβ”€β”€ styles/
β”‚   β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ hooks/
β”‚   β”œβ”€β”€ context/
β”‚   β”œβ”€β”€ pages/
β”‚   β”œβ”€β”€ utils/
β”‚   β”œβ”€β”€ routes/
β”‚   β”œβ”€β”€ store/
β”‚   β”‚   β”œβ”€β”€ slices/
β”‚   β”‚   β”œβ”€β”€ store.ts
β”‚   β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ theme/
β”‚   β”œβ”€β”€ tests/
β”œβ”€β”€ .gitignore
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ README.md
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ Detailed Folder Structure and Best Practices

πŸ”„ 1. Store – Redux State Management

This folder contains Redux store configuration and slices for state management.

store/
β”œβ”€β”€ slices/
β”‚   β”œβ”€β”€ authSlice.ts
β”‚   β”œβ”€β”€ userSlice.ts
β”‚   β”œβ”€β”€ themeSlice.ts
β”œβ”€β”€ store.ts
Enter fullscreen mode Exit fullscreen mode

Example Redux Slice:

import { createSlice, PayloadAction } from "@reduxjs/toolkit";

interface ThemeState {
  mode: "light" | "dark";
}

const initialState: ThemeState = {
  mode: "light",
};

const themeSlice = createSlice({
  name: "theme",
  initialState,
  reducers: {
    toggleTheme: (state) => {
      state.mode = state.mode === "light" ? "dark" : "light";
    },
  },
});

export const { toggleTheme } = themeSlice.actions;
export default themeSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

🌍 2. Context – Context API for Global State

Stores context providers for managing app-wide state without prop drilling.

context/
β”œβ”€β”€ AuthContext.tsx
β”œβ”€β”€ ThemeContext.tsx
β”œβ”€β”€ SidebarContext.tsx
Enter fullscreen mode Exit fullscreen mode

Example Sidebar Context API:

import React, { createContext, useState, ReactNode, useContext } from 'react';

type SidebarContextType = {
  isOpen: boolean;
  toggleSidebar: () => void;
};

const SidebarContext = createContext<SidebarContextType | undefined>(undefined);

export const SidebarProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [isOpen, setIsOpen] = useState(false);

  const toggleSidebar = () => setIsOpen(!isOpen);

  return (
    <SidebarContext.Provider value={{ isOpen, toggleSidebar }}>
      {children}
    </SidebarContext.Provider>
  );
};

export const useSidebar = () => {
  const context = useContext(SidebarContext);
  if (!context) throw new Error('useSidebar must be used within a SidebarProvider');
  return context;
};
Enter fullscreen mode Exit fullscreen mode

πŸ’… 3. Theme – Global Theme & Styled-Components

Stores the global theme configuration and styled-components for consistent UI styling.

Theme Configuration:

export const theme = {
  colors: {
    primary: "#007bff",
    secondary: "#6c757d",
    backgroundLight: "#ffffff",
    backgroundDark: "#121212",
  },
  spacing: {
    small: "8px",
    medium: "16px",
    large: "24px",
  },
};
Enter fullscreen mode Exit fullscreen mode

Example Styled Component:

import styled from "styled-components";

export const Button = styled.button`
  background-color: ${(props) => props.theme.colors.primary};
  color: white;
  padding: ${(props) => props.theme.spacing.medium};
  border-radius: 5px;
  cursor: pointer;
`;
Enter fullscreen mode Exit fullscreen mode

πŸ› οΈ 4. Hooks – Custom Hooks for Reusability

  • A place for storing reusable custom hooks.
  • Keeps logic modular and reusable.
hooks/
β”œβ”€β”€ useFetch.ts
β”œβ”€β”€ useDebounce.ts
β”œβ”€β”€ useTheme.ts
Enter fullscreen mode Exit fullscreen mode

Example Custom Hook:

import { useState, useEffect } from "react";

export function useDebounce(value: string, delay: number = 500) {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
}
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ 5. Testing Best Practices

  • Stores unit tests and integration tests.
  • Uses Jest and React Testing Library.
tests/
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ Button.test.tsx
β”œβ”€β”€ hooks/
β”‚   β”œβ”€β”€ useDebounce.test.ts
Enter fullscreen mode Exit fullscreen mode

Example Test Case:

import { render, screen } from "@testing-library/react";
import { Button } from "../../src/components/Button";

test("renders button correctly", () => {
  render(<Button>Click Me</Button>);
  expect(screen.getByText(/click me/i)).toBeInTheDocument();
});
Enter fullscreen mode Exit fullscreen mode

βœ… Conclusion

A scalable React project using TypeScript, styled-components, Redux, and Context API ensures:

  • πŸ”Ή Type safety with TypeScript.
  • πŸ”Ή Modular styling with styled-components.
  • πŸ”Ή Separation of concerns through hooks, services, and context.
  • πŸ”Ή Efficient state management via Redux Toolkit & Context API.
  • πŸ”Ή Reusability & Scalability with custom hooks & optimized folder structure.

πŸ€” How do you structure your React projects? Let’s discuss in the comments! πŸš€

Top comments (0)