Frontend Patterns
Component Design
Composition over Inheritance
// DOGRU: Composition
function Card({ children, header }: { children: ReactNode; header: ReactNode }) {
return (
<div className="card">
<div className="card-header">{header}</div>
<div className="card-body">{children}</div>
</div>
);
}
// Kullanim
<Card header={<h2>Title</h2>}>
<p>Content here</p>
</Card>
Container/Presenter Pattern
// Container: Data fetching + logic
function UserListContainer() {
const { data, isLoading } = useQuery(['users'], fetchUsers);
if (isLoading) return <Skeleton />;
return <UserList users={data} />;
}
// Presenter: Pure rendering
function UserList({ users }: { users: User[] }) {
return (
<ul>
{users.map(u => <UserItem key={u.id} user={u} />)}
</ul>
);
}
State Management
| Cozum |
Ne Zaman |
Karmasiklik |
| useState |
Local component state |
Dusuk |
| useReducer |
Complex local state |
Orta |
| Context |
Theme, auth, locale |
Dusuk-Orta |
| Zustand |
Global client state |
Orta |
| React Query |
Server state |
Orta |
| URL params |
Navigation state |
Dusuk |
Performance
// React.memo: Expensive render onleme
const ExpensiveList = React.memo(({ items }: { items: Item[] }) => (
<ul>{items.map(i => <ListItem key={i.id} item={i} />)}</ul>
));
// useMemo: Expensive hesaplama cache
const filtered = useMemo(
() => items.filter(i => i.status === status),
[items, status]
);
// useCallback: Referans stabilitesi
const handleClick = useCallback((id: string) => {
setSelected(id);
}, []);
Next.js Patterns
| Feature |
Ne Zaman |
| Server Component |
Data fetch, no interactivity |
| Client Component |
onClick, useState, useEffect |
| Route Handler |
API endpoint |
| Middleware |
Auth, redirect, rewrite |
| Streaming |
Buyuk data, progressive rendering |
shadcn/ui Best Practices
// Theme config: globals.css'te CSS variable kullan
// shadcn/ui dark mode: class strategy (Tailwind darkMode: 'class')
// Component override: cn() ile extend et, fork etme
import { Button } from '@/components/ui/button'
<Button variant="outline" className={cn('custom-class', className)} />
// Compose, override etme:
function SubmitButton({ children, ...props }: ButtonProps) {
return <Button type="submit" variant="default" {...props}>{children}</Button>
}
// A11y: shadcn radix tabanli, otomatik ARIA ama kontrol et
// Dark mode: CSS variable'lar otomatik switch eder
Performance Budget
| Metrik |
Esik |
Olcum |
| LCP (Largest Contentful Paint) |
< 2.5s |
Core Web Vital |
| CLS (Cumulative Layout Shift) |
< 0.1 |
Core Web Vital |
| INP (Interaction to Next Paint) |
< 200ms |
Core Web Vital |
| FCP (First Contentful Paint) |
< 1.8s |
Lighthouse |
| TTI (Time to Interactive) |
< 3.8s |
Lighthouse |
| Total JS bundle |
< 200KB gzipped |
Build analiz |
React Performance Top 10
React.memo sadece gercekten expensive render'larda
useMemo/useCallback sadece referans stability gerektiginde
- Code splitting:
React.lazy() + Suspense route bazli
- Image optimization:
next/image, lazy loading, WebP/AVIF
- Virtual scroll: 100+ item listede
@tanstack/virtual
- Debounce: Arama input'unda 300ms debounce
- Skeleton UI: Loading state icin layout shift onleme
- Bundle analyze:
@next/bundle-analyzer ile kontrol
- Prefetch:
<Link prefetch> kritik navigation'larda
- Server Component: Default RSC, client sadece interactive icin
Anti-Patterns
| Anti-Pattern |
Dogru Yol |
| Prop drilling (5+ level) |
Context veya state library |
| useEffect for derived state |
useMemo kullan |
| Index as key |
Unique ID kullan |
| Premature optimization |
Profiler ile olc, sonra optimize et |
1---2name: frontend-patterns3description: React, Next.js, TypeScript frontend patterns - component design, state management, performance4---56# Frontend Patterns78## Component Design910### Composition over Inheritance1112```tsx13// DOGRU: Composition14function Card({ children, header }: { children: ReactNode; header: ReactNode }) {15 return (16 <div className="card">17 <div className="card-header">{header}</div>18 <div className="card-body">{children}</div>19 </div>20 );21}2223// Kullanim24<Card header={<h2>Title</h2>}>25 <p>Content here</p>26</Card>27```2829### Container/Presenter Pattern3031```tsx32// Container: Data fetching + logic33function UserListContainer() {34 const { data, isLoading } = useQuery(['users'], fetchUsers);35 if (isLoading) return <Skeleton />;36 return <UserList users={data} />;37}3839// Presenter: Pure rendering40function UserList({ users }: { users: User[] }) {41 return (42 <ul>43 {users.map(u => <UserItem key={u.id} user={u} />)}44 </ul>45 );46}47```4849## State Management5051| Cozum | Ne Zaman | Karmasiklik |52|-------|----------|-------------|53| useState | Local component state | Dusuk |54| useReducer | Complex local state | Orta |55| Context | Theme, auth, locale | Dusuk-Orta |56| Zustand | Global client state | Orta |57| React Query | Server state | Orta |58| URL params | Navigation state | Dusuk |5960## Performance6162```tsx63// React.memo: Expensive render onleme64const ExpensiveList = React.memo(({ items }: { items: Item[] }) => (65 <ul>{items.map(i => <ListItem key={i.id} item={i} />)}</ul>66));6768// useMemo: Expensive hesaplama cache69const filtered = useMemo(70 () => items.filter(i => i.status === status),71 [items, status]72);7374// useCallback: Referans stabilitesi75const handleClick = useCallback((id: string) => {76 setSelected(id);77}, []);78```7980## Next.js Patterns8182| Feature | Ne Zaman |83|---------|----------|84| Server Component | Data fetch, no interactivity |85| Client Component | onClick, useState, useEffect |86| Route Handler | API endpoint |87| Middleware | Auth, redirect, rewrite |88| Streaming | Buyuk data, progressive rendering |8990## shadcn/ui Best Practices9192```typescript93// Theme config: globals.css'te CSS variable kullan94// shadcn/ui dark mode: class strategy (Tailwind darkMode: 'class')9596// Component override: cn() ile extend et, fork etme97import { Button } from '@/components/ui/button'98<Button variant="outline" className={cn('custom-class', className)} />99100// Compose, override etme:101function SubmitButton({ children, ...props }: ButtonProps) {102 return <Button type="submit" variant="default" {...props}>{children}</Button>103}104105// A11y: shadcn radix tabanli, otomatik ARIA ama kontrol et106// Dark mode: CSS variable'lar otomatik switch eder107```108109## Performance Budget110111| Metrik | Esik | Olcum |112|--------|------|-------|113| LCP (Largest Contentful Paint) | < 2.5s | Core Web Vital |114| CLS (Cumulative Layout Shift) | < 0.1 | Core Web Vital |115| INP (Interaction to Next Paint) | < 200ms | Core Web Vital |116| FCP (First Contentful Paint) | < 1.8s | Lighthouse |117| TTI (Time to Interactive) | < 3.8s | Lighthouse |118| Total JS bundle | < 200KB gzipped | Build analiz |119120### React Performance Top 101211221. `React.memo` sadece gercekten expensive render'larda1232. `useMemo`/`useCallback` sadece referans stability gerektiginde1243. Code splitting: `React.lazy()` + `Suspense` route bazli1254. Image optimization: `next/image`, lazy loading, WebP/AVIF1265. Virtual scroll: 100+ item listede `@tanstack/virtual`1276. Debounce: Arama input'unda 300ms debounce1287. Skeleton UI: Loading state icin layout shift onleme1298. Bundle analyze: `@next/bundle-analyzer` ile kontrol1309. Prefetch: `<Link prefetch>` kritik navigation'larda13110. Server Component: Default RSC, client sadece interactive icin132133## Anti-Patterns134135| Anti-Pattern | Dogru Yol |136|-------------|-----------|137| Prop drilling (5+ level) | Context veya state library |138| useEffect for derived state | useMemo kullan |139| Index as key | Unique ID kullan |140| Premature optimization | Profiler ile olc, sonra optimize et |