Clean β’ Professional
A well-structured React project is like a well-organized workspace β it saves time, reduces bugs, and makes collaboration easier. Whether youβre building a small app or a large-scale enterprise project, following clean architecture and consistent coding standards ensures your code remains maintainable, scalable, and easy to understand.
A good project structure helps you:
Poor structure, on the other hand, can make even small projects messy and difficult to maintain as they grow.
Hereβs a commonly used, scalable folder structure for modern React projects:
src/
βββ assets/ # Images, icons, fonts, videos
βββ components/ # Reusable UI components (Buttons, Inputs, Cards)
βββ pages/ # Page-level components (Home, About, Dashboard)
βββ hooks/ # Custom React Hooks (useAuth, useFetch)
βββ context/ # Context API files (ThemeContext, AuthContext)
βββ store/ # Redux, Zustand, or Recoil state management
βββ services/ # API calls and external services
βββ utils/ # Helper functions and utilities
βββ styles/ # Global CSS, SCSS, or styled-components themes
βββ routes/ # App routing configuration
βββ constants/ # App-wide constants and config variables
βββ App.js # Root component
βββ index.js # Entry point for ReactDOM.render
βββ setupTests.js # Jest/RTL configuration
components/ β Contains small, reusable building blocks like Button, Navbar, or Modalpages/ β Represents full-page views like HomePage, LoginPage, or ProfilePagehooks/ β Stores reusable custom hooks such as useForm or useFetchservices/ β Central place for API logic using Axios or Fetchcontext/ β Defines global app contexts (e.g., Theme, Auth)store/ β Manages state if using Redux Toolkit or Zustandutils/ β Contains helper functions (e.g., formatDate, validateEmail)styles/ β Centralized styling for consistent UI themesUserProfile.jsuseAuth.jsuser-icon.svgAPI_BASE_URLExample:
// Good
function UserCard() {}
// Bad
function user_card() {}
Instead of having one massive components folder, group related files by feature or domain.
src/
βββ features/
βββ auth/
β βββ LoginPage.jsx
β βββ RegisterPage.jsx
β βββ AuthContext.js
β βββ authService.js
βββ dashboard/
β βββ DashboardPage.jsx
β βββ ChartWidget.jsx
β βββ dashboardService.js
This makes it easier to maintain large applications as each feature is self-contained.
Maintaining consistency in your code style helps teams write clean, readable, and error-free code.
Here are some key standards to follow:
Install and configure ESLint and Prettier to automatically format and lint your code.
Example (ESLint + Prettier setup):
npm install eslint prettier eslint-config-prettier eslint-plugin-react --save-dev
Then create a .eslintrc.json file:
{
"extends": ["react-app", "prettier"],
"plugins": ["react"],
"rules": {
"react/prop-types": "off",
"no-unused-vars": "warn"
}
}
here,
Each component should handle one responsibility.
Avoid:
function Dashboard() {
// Handles API calls, rendering charts, managing modals, etc.
}
Instead, split logic:
function Dashboard() {
return (
<><DashboardHeader />
<UserStats />
<RecentActivities />
</>
);
}
Example:
// Good
const [userData, setUserData] = useState([]);
// Bad
const [a, b] = useState([]);
Keep data fetching and business logic separate from UI rendering.
Mixing logic inside components:
function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetchUsers().then(setUsers);
}, []);
return users.map(u => <p>{u.name}</p>);
}
Better approach:
// useUsers.js
export function useUsers() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetchUsers().then(setUsers);
}, []);
return users;
}
// UserList.jsx
import { useUsers } from "../hooks/useUsers";
function UserList() {
const users = useUsers();
return users.map(u => <p>{u.name}</p>);
}
Use PropTypes or TypeScript for validating props and ensuring type safety.
import PropTypes from "prop-types";
function UserCard({ name, age }) {
return <div>{name} β {age}</div>;
}
UserCard.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number
};
or with TypeScript:
type UserCardProps = {
name: string;
age?: number;
};
const UserCard = ({ name, age }: UserCardProps) => (
<div>{name} β {age}</div>
);
Use:
git commit often and write clear messages)src/
βββ api/
β βββ axiosInstance.js
βββ components/
β βββ Button.jsx
β βββ Card.jsx
β βββ Modal.jsx
βββ context/
β βββ AuthContext.js
βββ hooks/
β βββ useAuth.js
β βββ useFetch.js
βββ pages/
β βββ Home.jsx
β βββ Login.jsx
β βββ Dashboard.jsx
βββ store/
β βββ index.js
βββ styles/
β βββ globals.css
β βββ variables.scss
βββ utils/
βββ formatDate.js
| Practice | Benefit |
|---|---|
| Organized folder structure | Easy navigation and scalability |
| ESLint + Prettier | Consistent and clean code |
| Small, focused components | Reusable and testable |
| Separation of logic and UI | Better maintainability |
| Type checking | Fewer runtime errors |
| Documentation & Git | Easier collaboration |