# React.js Rules

Full coding rules for this stack. Read this in full before writing or modifying any React code in this project — not just once, keep applying it to every edit in the session, not only the first.

---

## Project Structure

```
src/
├── components/
│   ├── ui/                   # Generic, reusable UI (Button, Input, Modal...)
│   └── [feature]/            # Feature-specific components
├── pages/                    # Route-level components (thin, delegate to features)
├── features/                 # Self-contained feature modules
│   └── [feature]/
│       ├── components/       # UI specific to this feature
│       ├── hooks/            # Custom hooks for this feature
│       ├── api.ts            # API calls for this feature
│       ├── store.ts          # Zustand slice (if needed)
│       ├── types.ts          # TypeScript types/interfaces
│       └── index.ts          # Public exports
├── hooks/                    # Shared custom hooks
├── services/
│   └── api.ts                # Axios instance + interceptors
├── store/                    # Global Zustand store
├── types/                    # Shared TypeScript types
├── utils/                    # Pure utility functions
├── constants/                # App-wide constants
└── App.tsx
```

---

## Component Rules

### Always use Functional Components

- Never use class components.

### Define Props with TypeScript interface

- No `any`, no untyped `props` param.

### Keep components focused and small

- One component = one responsibility
- If a component exceeds ~150 lines, split it
- Extract logic to custom hooks, keep JSX clean

### Export convention

- Named export for regular components.
- Default export only for page-level components.

---

## Custom Hook Rules

- Prefix with `use`: `useUserList`, `useAuth`, `useModal`
- Extract all side effects, API calls, and complex state from components
- Return objects (not arrays) for multiple values — easier to destructure

---

## State Management Rules

### Server state → TanStack Query

Use for all API data (fetching, caching, mutations).

### Client/UI state → Zustand (or useState for local)

### Rules:
- **Never** use global state for server/API data — that's TanStack Query's job
- **Never** fetch in `useEffect` manually — use TanStack Query
- **Never** put loading/error state in Zustand — TanStack Query handles that

---

## Form Rules

Use **React Hook Form + Zod** for all forms — define the schema with Zod, infer the form type from it, wire it into `useForm` via `zodResolver`.

---

## API Layer Rules

One `axios` instance shared across the app with interceptors (attach auth token on request, handle 401 globally on response). Each feature gets its own thin API module built on that instance.

---

## TypeScript Rules

- **No `any`** — use `unknown`, proper types, or generics
- Define shared types in `types.ts` files
- Use `interface` for object shapes, `type` for unions/intersections
- Always type function return values for public hooks and API functions

---

## Styling Rules (Tailwind CSS)

- Use utility classes directly — avoid custom CSS unless necessary
- Extract repeated class combinations into components or a `cn()` helper
- Use `className` prop for external style overrides
- Never use inline `style={{ }}` for anything Tailwind can express

---

## Performance Rules

- Use `React.memo` only when profiling shows a real problem — do not optimize prematurely
- Use `useMemo` / `useCallback` for expensive computations or stable references passed to children
- Lazy-load routes with `React.lazy` + `Suspense`
- Avoid anonymous functions in JSX props when passing to memoized children

---

## Error Handling Rules

- Use React Error Boundary at the route level
- Handle API errors in TanStack Query `onError` callbacks
- Show user-friendly messages — never raw error objects
- Use toast notifications for async operation feedback

---

## Testing Rules

### Unit/Component tests with React Testing Library

- Test behavior, not implementation.

### Hook tests

- Use `renderHook` + `waitFor` from `@testing-library/react`.

---

## Naming Conventions

| Element | Convention | Example |
|---------|-----------|---------|
| Component file | PascalCase | `UserCard.tsx` |
| Hook file | camelCase | `useUserList.ts` |
| Utility file | camelCase | `formatDate.ts` |
| Type/Interface | PascalCase | `User`, `CreateUserRequest` |
| Component | PascalCase | `UserCard`, `OrderList` |
| Hook | `use` + PascalCase | `useUserList`, `useAuth` |
| Event handler | `handle` + Action | `handleDelete`, `handleSubmit` |
| Boolean variable | `is/has/can` prefix | `isLoading`, `hasError`, `canEdit` |
| Constant | UPPER_SNAKE_CASE | `MAX_RETRY`, `API_TIMEOUT` |
| CSS class (custom) | kebab-case | `user-card`, `nav-item` |

---

## Common Anti-Patterns to Avoid

- ❌ Fetching in `useEffect` → use TanStack Query
- ❌ Using `any` type → define proper TypeScript types
- ❌ Storing server data in Zustand → that's TanStack Query's responsibility
- ❌ Class components → use functional components
- ❌ `index.js` everywhere → use named files for traceability
- ❌ Direct DOM manipulation → use React state/refs
- ❌ Mutating state directly → always use setter functions
- ❌ Large components doing everything → split into smaller focused components
- ❌ Prop drilling more than 2 levels → use context or Zustand
- ❌ Hardcoding API URLs → use `import.meta.env.VITE_API_URL`

---

When explaining changes, refer to the [React Official Documentation](https://react.dev), [TanStack Query](https://tanstack.com/query), and [React Hook Form](https://react-hook-form.com) conventions.
