React, kullanıcı arayüzleri oluşturmak için en popüler JavaScript kütüphanesidir. Bu rehberde modern React ekosistemini kullanarak sıfırdan üretim kalitesinde bir web uygulaması geliştireceğiz. Vite, React Router, Zustand ve TanStack Query gibi güncel araçlarla gerçek dünya projelerinde kullanabileceğiniz bir temel oluşturacağız.

Proje Başlatma: Vite vs Create React App

İlgili rehberler: Yazılım geliştirme süreçleri · PostgreSQL optimizasyonu · Git ileri seviye komutlar · Redis nedir, nasıl kullanılır · Docker ile deploy

Create React App (CRA) artık resmi olarak önerilmiyor. Vite, ESBuild tabanlı derleme sistemiyle çok daha hızlı geliştirme deneyimi sunar. Hot Module Replacement (HMR) milisaniyeler içinde gerçekleşir.

ÖzellikCreate React AppVite
Dev server başlatma~10-30 saniye~300ms
HMR süresi1-5 saniye~50ms
Build araçlarıWebpackESBuild + Rollup
YapılandırmaGizli (eject gerekir)Açık ve basit
Resmi destek (2026)SonlandırıldıAktif geliştirme
TypeScriptEk kurulumYerleşik destek
# Vite ile React + TypeScript projesi oluştur
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev   # http://localhost:5173 açılır
my-app/
├── public/
│   └── vite.svg
├── src/
│   ├── assets/
│   ├── components/
│   │   ├── ui/           # Genel UI bileşenleri
│   │   └── layout/       # Header, Footer, Sidebar
│   ├── pages/            # Sayfa bileşenleri
│   ├── hooks/            # Özel hook'lar
│   ├── services/         # API çağrıları
│   ├── store/            # State management
│   ├── types/            # TypeScript tipleri
│   ├── utils/            # Yardımcı fonksiyonlar
│   ├── App.tsx
│   └── main.tsx
├── .env
├── vite.config.ts
└── package.json

Component Mimarisi

React'te her şey bileşendir (component). İyi bir bileşen yapısı; tek sorumluluk ilkesine uyar, yeniden kullanılabilir, ve test edilebilir olmalıdır. Props ile veri alır, kendi iç state'ini yönetir.

// src/components/ui/Button.tsx
import { ButtonHTMLAttributes, ReactNode } from 'react';

interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: 'primary' | 'secondary' | 'danger';
  size?: 'sm' | 'md' | 'lg';
  loading?: boolean;
  children: ReactNode;
}

export function Button({
  variant = 'primary',
  size = 'md',
  loading = false,
  children,
  className = '',
  disabled,
  ...props
}: ButtonProps) {
  const baseClasses = 'inline-flex items-center justify-center font-medium rounded-lg transition-colors';
  const variantClasses = {
    primary: 'bg-blue-600 text-white hover:bg-blue-700',
    secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
    danger: 'bg-red-600 text-white hover:bg-red-700'
  };
  const sizeClasses = {
    sm: 'px-3 py-1.5 text-sm',
    md: 'px-4 py-2 text-base',
    lg: 'px-6 py-3 text-lg'
  };

  return (
    <button
      className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}
      disabled={disabled || loading}
      {...props}
    >
      {loading && <span className="animate-spin mr-2">⟳</span>}
      {children}
    </button>
  );
}

React Hooks Derinlemesine

Hook'lar, fonksiyonel bileşenlerde state, side effect ve context gibi React özelliklerini kullanmanızı sağlar. En çok kullanılan hook'lar useState, useEffect, useMemo, useCallback ve useRef'tir.

Özel Hook Yazma

Tekrarlayan mantığı özel hook'lara taşıyarak kodunuzu DRY (Don't Repeat Yourself) tutabilirsiniz. Aşağıda API çağrıları için kullanışlı bir useFetch hook'u:

// src/hooks/useFetch.ts
import { useState, useEffect } from 'react';

interface UseFetchResult<T> {
  data: T | null;
  loading: boolean;
  error: string | null;
  refetch: () => void;
}

export function useFetch<T>(url: string): UseFetchResult<T> {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [trigger, setTrigger] = useState(0);

  useEffect(() => {
    const controller = new AbortController();
    setLoading(true);
    setError(null);

    fetch(url, { signal: controller.signal })
      .then(res => {
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return res.json();
      })
      .then(json => setData(json))
      .catch(err => {
        if (err.name !== 'AbortError') setError(err.message);
      })
      .finally(() => setLoading(false));

    return () => controller.abort();
  }, [url, trigger]);

  const refetch = () => setTrigger(t => t + 1);
  return { data, loading, error, refetch };
}
İpucu
Gerçek projelerde useFetch yerine TanStack Query (React Query) kullanmanızı öneririz. Caching, background refetch, stale-while-revalidate gibi gelişmiş özellikler sunar.

State Management: Zustand

Global state yönetimi için Zustand, Redux'a kıyasla çok daha az boilerplate gerektirir. Küçük ve orta ölçekli projelerde ideal bir seçimdir. TypeScript desteği yerleşiktir.

npm install zustand
// src/store/authStore.ts
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

interface User {
  id: number;
  name: string;
  email: string;
}

interface AuthState {
  user: User | null;
  token: string | null;
  isAuthenticated: boolean;
  login: (user: User, token: string) => void;
  logout: () => void;
}

export const useAuthStore = create<AuthState>()(
  persist(
    (set) => ({
      user: null,
      token: null,
      isAuthenticated: false,

      login: (user, token) => set({
        user,
        token,
        isAuthenticated: true
      }),

      logout: () => set({
        user: null,
        token: null,
        isAuthenticated: false
      })
    }),
    { name: 'auth-storage' } // localStorage'a kaydeder
  )
);

// Kullanım:
// const { user, login, logout } = useAuthStore();
// login({ id: 1, name: 'Ali', email: 'ali@test.com' }, 'jwt-token');

API Entegrasyonu

API çağrılarını merkezi bir servis katmanında toplamak, bakım kolaylığı sağlar. Axios veya native fetch ile bir API istemcisi oluşturup, tüm endpointleri buradan yönetebilirsiniz.

// src/services/api.ts
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api';

async function request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
  const token = localStorage.getItem('auth-storage');
  const parsed = token ? JSON.parse(token) : null;

  const res = await fetch(`${API_URL}${endpoint}`, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...(parsed?.state?.token && {
        Authorization: `Bearer ${parsed.state.token}`
      }),
      ...options.headers
    }
  });

  if (!res.ok) {
    const error = await res.json().catch(() => ({ error: 'Sunucu hatası' }));
    throw new Error(error.error || `HTTP ${res.status}`);
  }

  return res.json();
}

// API endpoint'leri
export const api = {
  auth: {
    login: (data: { email: string; password: string }) =>
      request('/auth/login', { method: 'POST', body: JSON.stringify(data) }),
    register: (data: { name: string; email: string; password: string }) =>
      request('/auth/register', { method: 'POST', body: JSON.stringify(data) })
  },
  users: {
    list: (page = 1) => request(`/users?page=${page}`),
    get: (id: number) => request(`/users/${id}`),
    update: (id: number, data: any) =>
      request(`/users/${id}`, { method: 'PUT', body: JSON.stringify(data) })
  }
};

React Router ile Sayfa Yönlendirme

npm install react-router-dom
// src/App.tsx
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { useAuthStore } from './store/authStore';
import Layout from './components/layout/Layout';
import Home from './pages/Home';
import Login from './pages/Login';
import Dashboard from './pages/Dashboard';
import NotFound from './pages/NotFound';

// Korumalı rota bileşeni
function ProtectedRoute({ children }: { children: React.ReactNode }) {
  const isAuthenticated = useAuthStore(s => s.isAuthenticated);
  return isAuthenticated ? <>{children}</> : <Navigate to="/login" replace />;
}

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route element={<Layout />}>
          <Route path="/" element={<Home />} />
          <Route path="/login" element={<Login />} />
          <Route
            path="/dashboard"
            element={
              <ProtectedRoute>
                <Dashboard />
              </ProtectedRoute>
            }
          />
          <Route path="*" element={<NotFound />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

Build ve Deploy

Vite, üretim build'ini Rollup ile oluşturur. Otomatik code splitting, tree shaking ve minification uygular. Çıktı dist/ klasörüne yazılır ve herhangi bir statik dosya sunucusunda host edilebilir.

# Üretim build
npm run build

# Build çıktısını test et
npm run preview  # http://localhost:4173

# Build dosya boyutlarını analiz et
npx vite-bundle-visualizer
// vite.config.ts — üretim optimizasyonları
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  build: {
    target: 'es2020',
    minify: 'terser',
    sourcemap: false,
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          router: ['react-router-dom']
        }
      }
    }
  },
  server: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
});
Bilgi
SPA (Single Page Application) deploy ederken, tüm rotaların index.html'e yönlendirildiğinden emin olun. Nginx için: try_files $uri $uri/ /index.html;

Performans İpuçları

  • React.lazy() ve Suspense ile code splitting uygulayın — her sayfa ayrı chunk olarak yüklenir
  • useMemo ve useCallback ile gereksiz render'ları önleyin
  • Görselleri WebP/AVIF formatında ve lazy loading ile yükleyin
  • Virtualization (react-window/tanstack-virtual) ile uzun listeleri optimize edin
  • React DevTools Profiler ile render performansını analiz edin
  • Bundle boyutunu izleyin — vendor chunk'ın 200KB altında kalmasını hedefleyin
// Lazy loading örneği
import { lazy, Suspense } from 'react';

const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <Suspense fallback={<div className="p-8 text-center">Yükleniyor...</div>}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

Modern Yazılım Geliştirme ve DevOps Pratikleri

Profesyonel yazılım geliştirme süreci üç pillar üzerine kuruludur: kaynak kontrolü (Git + GitHub/GitLab pull request akışı, code review zorunlu), CI/CD pipeline (otomatik test + lint + build + deploy), ve gözlemlenebilirlik (Sentry/Datadog/Grafana ile log, metric, trace toplama). Test piramidi (unit > integration > e2e) ile kod kalitesini garantilemek, mikroservis mimarisinde Docker container ve Kubernetes orkestrasyonu kullanmak, REST veya GraphQL API tasarımında OpenAPI/GraphQL Schema sözleşmesi tutmak modern standardlardır. Yazılım geliştirme yaşam döngüsü boyunca (gereksinim → tasarım → implementasyon → test → deploy → bakım) Agile/Scrum sprintleri 1-2 hafta, DevOps takımları sürekli teslim (continuous delivery) prensibiyle çalışır.

React uygulamalarınızı hızlı ve güvenilir sunucularda barındırmak için KEYDAL hosting planlarını inceleyin.

WhatsApp