Ders 02: Routing - Temel Seviye
🎯 Bu Derste Neleri Öğreneceksiniz?
Section titled “🎯 Bu Derste Neleri Öğreneceksiniz?”- File-based routing sistemi nasıl çalışır?
- Yeni sayfalar/route’lar nasıl oluşturulur?
- Route parametreleri nasıl kullanılır?
- Link bileşeniyle sayfalar arası geçiş nasıl yapılır?
- Route’lar arası veri paylaşımı (nested routes)
📚 Routing’e Giriş
Section titled “📚 Routing’e Giriş”TanStack Start, TanStack Router kullanarak file-based routing sunar. Bu, dosya sisteminizdeki yapının doğrudan URL yapısına karşılık geldiği anlamına gelir.
Temel Kavramlar
Section titled “Temel Kavramlar”| Kavram | Açıklama |
|---|---|
| File-based routing | Dosya yolu URL’ye dönüşür |
| Route | Belirli bir URL’e karşılık gelen sayfa |
| Nested routes | İç içe geçmiş route’lar |
| Route params | URL’den dinamik veri alma (:id gibi) |
| Outlet | Çocuk route’ları render eden bileşen |
🔨 Yeni Sayfa Oluşturma
Section titled “🔨 Yeni Sayfa Oluşturma”Basit Statik Sayfa
Section titled “Basit Statik Sayfa”Hadi hakkimizda sayfası oluşturalım!
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/hakkimizda')({ component: HakkimizdaPage,})
function HakkimizdaPage() { return ( <div style={{ padding: '2rem' }}> <h1>Hakkımızda</h1> <p>Biz TanStack Start öğreniyoruz!</p> <p>Bu kurs, modern React geliştirme üzerine odaklanmıştır.</p> </div> )}Şimdi tarayıcıda http://localhost:3000/hakkimizda adresine gidin.
Dikkat: Dosya ismi ve createFileRoute içindeki path aynı olmalıdır!
Dosya İsmi → URL Eşleşmesi
Section titled “Dosya İsmi → URL Eşleşmesi”| Dosya Yolu | URL | Açıklama |
|---|---|---|
src/routes/index.tsx | / | Ana sayfa |
src/routes/hakkimizda.tsx | /hakkimizda | Hakkımızda |
src/routes/iletisim.tsx | /iletisim | İletişim |
src/products.tsx | /products | Products |
src/products/index.tsx | /products | Products (alternatif) |
🔗 Link Kullanımı
Section titled “🔗 Link Kullanımı”TanStack Start, kendi Link bileşenini sunar. Bu bileşen type-safe’tir ve navigasyon optimize eder.
Temel Link Kullanımı
Section titled “Temel Link Kullanımı”import { createFileRoute, Link } from '@tanstack/react-router'
export const Route = createFileRoute('/')({ component: HomePage,})
function HomePage() { return ( <div> <h1>Ana Sayfa</h1> <nav> <ul style={{ display: 'flex', gap: '1rem', listStyle: 'none' }}> <li> <Link to="/hakkimizda">Hakkımızda</Link> </li> <li> <Link to="/iletisim">İletişim</Link> </li> <li> <Link to="/urunler">Ürünler</Link> </li> </ul> </nav> <p>Ana sayfa içeriği buraya...</p> </div> )}Aktif Link Stili
Section titled “Aktif Link Stili”Aktif link’i stillemek için activeProps kullanabilirsiniz:
function Navigation() { return ( <nav> <ul style={{ display: 'flex', gap: '1rem', listStyle: 'none' }}> <li> <Link to="/" activeProps={{ style: { color: 'blue', fontWeight: 'bold' } }} > Ana Sayfa </Link> </li> <li> <Link to="/hakkimizda" activeProps={{ style: { color: 'blue', fontWeight: 'bold' } }} > Hakkımızda </Link> </li> </ul> </nav> )}🎯 Dinamik Route Parametreleri
Section titled “🎯 Dinamik Route Parametreleri”E-commerce sitesi düşünün: her ürünün kendi sayfası olmalı. URL şöyle olmalı: /urunler/urun-1, /urunler/urun-2, vb.
Dinamik Route Oluşturma
Section titled “Dinamik Route Oluşturma”# src/routes/urunler/$urunId.tsx$ işareti, bu kısmın dinamik olduğunu gösterir.
// src/routes/urunler/$urunId.tsximport { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/urunler/$urunId')({ component: UrunDetayPage,})
function UrunDetayPage() { // URL parametresine eriş const { urunId } = Route.useParams()
return ( <div style={{ padding: '2rem' }}> <h1>Ürün Detayı</h1> <p>Ürün ID: <strong>{urunId}</strong></p> <p>Bu ürünün detayları yakında buraya gelecek...</p> </div> )}Şimdi bu sayfaya gidin:
/urunler/urun-1→ “Ürün ID: urun-1”/urunler/abc-123→ “Ürün ID: abc-123”
Birden Fazla Parametre
Section titled “Birden Fazla Parametre”# src/routes/kategoriler/$kategoriId/urunler/$urunId.tsxexport const Route = createFileRoute('/kategoriler/$kategoriId/urunler/$urunId')({ component: UrunInKategoriPage,})
function UrunInKategoriPage() { const { kategoriId, urunId } = Route.useParams()
return ( <div> <h1>Ürün: {urunId}</h1> <p>Kategori: {kategoriId}</p> </div> )}URL: /kategoriler/elektronik/urunler/laptop-123
---
## 🌳 Nested Routing (İç İçe Route'lar)
Nested routing, bir route'un içinde başka bir route'un çalışmasıdır. Bu, layout'ları paylaşmak için harika bir yöntemdir!
### Layout Route Oluşturma
```bash# src/routes/dashboard.tsx (Layout)# src/routes/dashboard/index.tsx (Ana sayfa)# src/routes/dashboard/ayarlarr.tsx (Ayarlar sayfası)Dashboard Layout (dashboard.tsx):
import { createFileRoute, Outlet, Link } from '@tanstack/react-router'
export const Route = createFileRoute('/dashboard')({ component: DashboardLayout,})
function DashboardLayout() { return ( <div style={{ display: 'flex', minHeight: '100vh' }}> {/* Sidebar */} <aside style={{ width: '250px', backgroundColor: '#f3f4f6', padding: '1rem' }}> <h2>Dashboard</h2> <nav> <ul style={{ listStyle: 'none', padding: 0 }}> <li style={{ marginBottom: '0.5rem' }}> <Link to="/dashboard">Ana Sayfa</Link> </li> <li style={{ marginBottom: '0.5rem' }}> <Link to="/dashboard/ayarlarr">Ayarlar</Link> </li> <li style={{ marginBottom: '0.5rem' }}> <Link to="/dashboard/profil">Profil</Link> </li> </ul> </nav> </aside>
{/* Main Content - Çocuk route'lar buraya render edilir */} <main style={{ flex: 1, padding: '2rem' }}> <Outlet /> </main> </div> )}Dashboard Ana Sayfa (dashboard/index.tsx):
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/dashboard/')({ component: DashboardHome,})
function DashboardHome() { return ( <div> <h1>Dashboard Ana Sayfa</h1> <p>Dashboard'a hoş geldiniz!</p> </div> )}Dashboard Ayarlar (dashboard/ayarlarr.tsx):
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/dashboard/ayarlarr')({ component: AyarlarrPage,})
function AyarlarrPage() { return ( <div> <h1>Ayarlar</h1> <p>İşte ayarlar sayfanız...</p> </div> )}Nested Route Yapısı
Section titled “Nested Route Yapısı”/dashboard → DashboardLayout (sidebar + outlet) ├── /dashboard/ → DashboardHome ├── /dashboard/ayarlarr → AyarlarrPage └── /dashboard/profil → ProfilPage💡 Önemli:
dashboard.tsx’de<Outlet />bileşeni, çocuk route’ların nerede render edileceğini belirler.
🔄 Navigasyon Programatik
Section titled “🔄 Navigasyon Programatik”Bazen JavaScript ile navigasyon yapmanız gerekir.
useNavigate Hook
Section titled “useNavigate Hook”import { createFileRoute } from '@tanstack/react-router'import { useNavigate } from '@tanstack/react-router'
export const Route = createFileRoute('/form')({ component: FormPage,})
function FormPage() { const navigate = useNavigate()
const handleSubmit = () => { // Form gönderildiğinde ana sayfaya git navigate({ to: '/' }) }
const goBack = () => { // Bir sayfa geri git navigate({ to: '..' }) }
return ( <div> <h1>Form Sayfası</h1> <button onClick={handleSubmit}>Gönder ve Ana Sayfaya Git</button> <button onClick={goBack}>Geri</button> </div> )}Navigasyon Seçenekleri
Section titled “Navigasyon Seçenekleri”// Basit navigasyonnavigate({ to: '/hakkimizda' })
// Bir sayfa gerinavigate({ to: '..' })
// İki sayfa ilerinavigate({ to: '../sibling' })
// Query param ile navigasyonnavigate({ to: '/arama', search: { q: 'tanstack' }})
// Replace (geçmişe eklemez)navigate({ to: '/login', replace: true})🎨 Pratik Örnek: Blog Uygulaması
Section titled “🎨 Pratik Örnek: Blog Uygulaması”Hadi öğrendiklerimizi bir blog uygulamasıyla pekiştirelim!
Blog Yapısı
Section titled “Blog Yapısı”/├── blog.tsx (Layout - ortak header/footer)│ ├── index.tsx (Blog listesi)│ └── $slug.tsx (Blog detay)Blog Layout (blog.tsx):
import { createFileRoute, Outlet, Link } from '@tanstack/react-router'
export const Route = createFileRoute('/blog')({ component: BlogLayout,})
function BlogLayout() { return ( <div> {/* Ortak Header */} <header style={{ backgroundColor: '#3b82f6', color: 'white', padding: '1rem 2rem', marginBottom: '2rem' }}> <Link to="/" style={{ color: 'white', textDecoration: 'none' }}> 📝 Blogum </Link> <span style={{ marginLeft: '2rem' }}> <Link to="/blog" style={{ color: 'white', textDecoration: 'none' }}> Yazılar </Link> </span> </header>
{/* Blog İçeriği */} <main style={{ maxWidth: '800px', margin: '0 auto', padding: '0 1rem' }}> <Outlet /> </main>
{/* Ortak Footer */} <footer style={{ marginTop: '3rem', padding: '2rem', backgroundColor: '#f3f4f6', textAlign: 'center' }}> <p>© 2025 Blogum - Tüm hakları saklıdır.</p> </footer> </div> )}Blog Liste (blog/index.tsx):
import { createFileRoute, Link } from '@tanstack/react-router'
const YAZILAR = [ { slug: 'tanstack-starta-giris', title: 'TanStack Start\'a Giriş', excerpt: 'Modern React framework' }, { slug: 'routing-nedir', title: 'Routing Nedir?', excerpt: 'File-based routing sistemi' }, { slug: 'server-functions', title: 'Server Functions', excerpt: 'Type-safe RPC' },]
export const Route = createFileRoute('/blog/')({ component: BlogListe,})
function BlogListe() { return ( <div> <h1 style={{ fontSize: '2rem', marginBottom: '2rem' }}>Yazılar</h1> {YAZILAR.map((yazi) => ( <article key={yazi.slug} style={{ border: '1px solid #e5e7eb', borderRadius: '8px', padding: '1.5rem', marginBottom: '1.5rem' }} > <Link to={`/blog/${yazi.slug}`} style={{ textDecoration: 'none', color: 'inherit' }} > <h2 style={{ fontSize: '1.5rem', marginBottom: '0.5rem' }}> {yazi.title} </h2> <p style={{ color: '#6b7280' }}>{yazi.excerpt}</p> </Link> </article> ))} </div> )}Blog Detay (blog/$slug.tsx):
// src/routes/blog/$slug.tsximport { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/blog/$slug')({ component: BlogDetay,})
function BlogDetay() { const { slug } = Route.useParams()
return ( <article> <h1>Yazı Detayı: {slug}</h1> <p>Bu yazı için detaylı içerik yakında buraya gelecek...</p> <Link to="/blog">← Listeye Dön</Link> </article> )}✅ Ders 2 Özeti
Section titled “✅ Ders 2 Özeti”Bu derste öğrendiklerimiz:
| Konu | Açıklama |
|---|---|
| File-based routing | Dosya yolu URL’ye dönüşür |
| Statik route | Sabit URL’li sayfa (hakkimizda.tsx) |
| Dinamik route | Parametreli URL ($param) |
| Link | Sayfalar arası geçiş bileşeni |
| useParams | Route parametrelerini alma |
| Outlet | Nested routing için çocuk render alanı |
| useNavigate | Programatik navigasyon |
| Nested routes | İç içe route’lar, layout paylaşımı |
📝 Alıştırmalar
Section titled “📝 Alıştırmalar”Alıştırma 1: Portföyö Sayfası
Section titled “Alıştırma 1: Portföyö Sayfası”Kişisel portföyö siteniz için şu sayfaları oluşturun:
/- Ana sayfa/hakkimda- Hakkımda sayfası/projeler- Projeler listesi/projeler/$id- Proje detay sayfası
İpucu: Layout kullanarak ortak bir header/footer tasarlayın.
Alıştırma 2: E-Commerce Kategorileri
Section titled “Alıştırma 2: E-Commerce Kategorileri”Bir e-ticaret sitesi kategorileri oluşturun:
/├── shop.tsx (Layout)│ ├── index.tsx (Tüm ürünler)│ ├── elektronik.tsx│ ├── giyim.tsx│ └── $kategori/$urun.tsx (Ürün detay)Alıştırma 3: Aktif Navigasyon
Section titled “Alıştırma 3: Aktif Navigasyon”Navigasyon bileşeni oluşturun ki:
- Aktif sayfa linki kalın ve mavi olsun
- Aktif olmayan linkler normal görünsün
- Hover efekti ekleyin
🚀 Sonraki Ders: Routing - Orta Seviye
Section titled “🚀 Sonraki Ders: Routing - Orta Seviye”Bir sonraki derste şunları öğreneceksiniz:
- 🔍 Search params ile arama yapma
- 📦 Data loading ve loader fonksiyonları
- ⏳ Loading ve error states
- 🔄 Data revalidation ve caching
- 🎯 Redirects ve 404 handling
💬 Sorularınız?
Section titled “💬 Sorularınız?”- Nested routing’de
Outletzorunlu mu? - Birden fazla dinamik parametre kullanabilir miyiz?
- Link vs normal
<a>tag farkı nedir?
Bir sonraki derste görüşmek üzere! 👋