- The coding style shall follow the JavaScript Standard Style.
src/
├─ assets/ # Static assets (images, fonts, etc.)
├─ components/ # Reusable UI components
├─ pages/ # Top-level components for each route
├─ hooks/ # Custom React hooks for shared logic
├─ styles/ # Global styles and Tailwind configuration
├─ utils/ # Helper functions and utility classes
├─ services/ # API calls and external service integrations (e.g., api.ts)
├─ App.tsx # Main application component
└─ main.tsx # Entry point of the application
-
Components: Use PascalCase and the
.tsx
file extension (e.g., Header.tsx
, NoteCard.tsx
).
-
Files & Helpers: Use camelCase for all other files (e.g.,
formatDate.ts
, api.ts
).
-
Types/Interfaces: Use PascalCase (e.g.,
User
, ApiResponse
).
-
Constants: Use UPPER_CASE with underscores (e.g.,
API_BASE_URL
).
-
Variables, Functions: Use descriptive camelCase (e.g.,
userName
, formatDate
).
-
Booleans: Prefix with is, has, or can (e.g.,
isUserLoggedIn
).
- Use functional components (not class).
- Keep components small and focused.
- Order: imports → hooks/state → handlers → JSX return.
- Use TypeScript interfaces/types for props.
- Mark optional props with
?
and set default values using default parameters.
import React from "react";
interface NoteCardProps {
title: string;
content: string;
onDelete: () => void;
age?: number; // optional
}
const NoteCard: React.FC<NoteCardProps> = ({ title, content, onDelete, age = 18 }) => {
const handleClick = () => onDelete();
return (
<div className="note">
<h1>{title}</h1>
<p>{content} - {age}</p>
<button onClick={handleClick}>Delete</button>
</div>
);
};
export default NoteCard;
- Use Tailwind CSS.
- Class names should be readable and grouped logically.
- Use conditional classes with template strings.
<button className={isActive ? "bg-blue-500" : "bg-gray-300"}>
Click
</button>
- Use React hooks such as
useState
, useEffect
, and others.
- Always define types explicitly when they cannot be inferred.
- Use union types or generic parameters for complex states.
- Extract repeated logic into custom hooks with proper typing.
const [count, setCount] = useState<number>(0);
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
console.log("User changed:", user);
}, [user]);
// Example of a custom hook
function useToggle(initialValue: boolean = false): [boolean, () => void] {
const [value, setValue] = useState<boolean>(initialValue);
const toggle = () => setValue((prev) => !prev);
return [value, toggle];
}
- Group imports in the following order:
- React.
- External libraries.
- Local Files: Components, hooks, or utils from within the project.
- Use absolute imports (configured in tsconfig.json) instead of long relative paths.
- Avoid unused imports; enforce cleanup with ESLint.
-
Naming: Use descriptive names prefixed with a verb (e.g.,
handleClick
, handleSubmit
).
-
Placement: Define
handler
functions above the return statement.
-
Typing: Always specify event types for clarity and safety.
// Input change event
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
// Form submit event
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// submit logic
};
// Button click event
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
console.log("Button clicked");
};