Svelte 5 Runes Rehberi 2026: $state, $derived, $effect ile Yeni Reactivity Sistemi

Ana SayfaHaberler › Svelte 5 Runes Rehberi 2026: $state, $derived, $effe...

Svelte 5 Runes Rehberi 2026: $state, $derived, $effect ile Yeni Reactivity Sistemi

16.05.2026 1 görüntülenme

Svelte 5'in en büyük yeniliği Runes sistemidir (the biggest innovation in Svelte 5 is Runes). Bu yeni reactivity yaklaşımı (new reactivity approach), eski $: reactive statement syntax'ının yerine geçiyor ve TypeScript ile daha iyi entegrasyon, daha öngörülebilir davranış (more predictable behavior) ve daha az "magic" sunuyor. Alesta Web olarak bu yazımızda; $state, $derived, $effect, $props, $bindable rune'larını gerçek kod örnekleriyle anlatıyor, Svelte 4'ten migration adımlarını gösteriyoruz.

1. Runes Nedir? (What are Runes?)

Runes, Svelte 5 ile gelen yeni reactivity API'sidir (new reactivity API). Eski Svelte 4'te let count = 0 yazıp count++ yaptığınızda compiler arka planda reaktivite kodu üretiyordu (compiler generated reactivity code in background). Bu "magic" hem kafa karıştırıcıydı (confusing) hem de TypeScript tarafında bazı tuhaflıklar yaratıyordu.

Svelte 5 ile birlikte reactivity explicit hale geldi (became explicit). Artık değişkenlerinizin reaktif olduğunu açıkça belirtmeniz gerekiyor (you must explicitly mark variables as reactive):

<!-- Svelte 4 (eski / old) -->
<script>
  let count = 0;
  $: doubled = count * 2;
</script>

<!-- Svelte 5 (yeni / new — Runes) -->
<script>
  let count   = $state(0);
  let doubled = $derived(count * 2);
</script>
💡 Bilgi / Info:

Runes, bir komponent içinde $state veya başka bir rune kullandığınızda otomatik olarak aktifleşir (auto-activated). Aynı projede bazı komponentler "runes mode", bazıları "legacy mode" olabilir — bu sayede aşamalı migration mümkün (gradual migration possible).

2. $state Rune'u — Reactive Variables

$state, reaktif (değişiklikleri DOM'a yansıyan) değişken oluşturmanın yoludur (way to create reactive variables that reflect to DOM).

<script>
  // Primitif değer (primitive value)
  let count = $state(0);

  // Object (nested reactivity — Proxy ile)
  let user = $state({ name: 'Ahmet', age: 28 });

  // Array
  let todos = $state([]);

  function increment() {
    count++;   // Otomatik re-render (auto re-render)
  }

  function updateUser() {
    user.name = 'Mehmet';  // Nested update da reaktif
  }

  function addTodo(text) {
    todos.push({ id: Date.now(), text }); // Array mutation reaktif
  }
</script>

<button onclick={increment}>Sayı: {count}</button>
<p>Kullanıcı: {user.name} ({user.age})</p>

2.1 $state.raw — Performans için (For Performance)

<script>
  // Büyük data yapıları için (Proxy overhead'i olmadan)
  // For large data structures (no Proxy overhead)
  let bigList = $state.raw(largeDataArray);

  function update() {
    bigList = [...bigList, newItem]; // Yeni referans atayarak güncelle
  }
</script>

2.2 $state.snapshot — Reaktif Değeri Plain JS'e Dönüştür

<script>
  let user = $state({ name: 'Ali', age: 30 });

  // API'ye gönderirken Proxy yerine plain object
  // Plain object instead of Proxy when sending to API
  async function save() {
    const plainUser = $state.snapshot(user);
    await fetch('/api/users', {
      method: 'POST',
      body: JSON.stringify(plainUser)
    });
  }
</script>

3. $derived Rune'u — Computed Values

$derived, başka reaktif değerlerden hesaplanan değerler oluşturmaya yarar (creates values computed from other reactive values). Vue'daki computed veya React'taki useMemo benzeri (similar to Vue's computed or React's useMemo).

<script>
  let firstName = $state('Ahmet');
  let lastName  = $state('Yılmaz');

  // Otomatik tracking (automatic tracking)
  let fullName = $derived(firstName + ' ' + lastName);

  // Karmaşık hesaplama için $derived.by
  let initials = $derived.by(() => {
    return firstName[0] + lastName[0];
  });
</script>

<p>Tam Ad: {fullName}</p>
<p>Baş Harfler: {initials}</p>
✅ Avantaj:

$derived değerleri lazy hesaplanır (lazily computed) — sadece okunduğunda recompute olur. Memoization built-in.

4. $effect Rune'u — Side Effects

$effect, reaktif değerler değiştiğinde çalışan side effect'leri tanımlar (defines side effects that run when reactive values change). React'taki useEffect'in eşdeğeri (equivalent of React's useEffect) ama daha az kafa karıştırıcı.

<script>
  let count = $state(0);

  $effect(() => {
    console.log('Count değişti:', count);

    // Cleanup function (Türkçesi: temizlik fonksiyonu)
    return () => {
      console.log('Cleanup:', count);
    };
  });

  // Sadece component mount edildiğinde çalışan effect
  $effect.pre(() => {
    // DOM güncellemesinden önce çalışır
    // Runs before DOM update
  });

  // Manuel root effect (component dışında)
  const cleanup = $effect.root(() => {
    $effect(() => {
      console.log('Root effect');
    });
    return () => console.log('Root cleanup');
  });
</script>
⚠️ Dikkat / Warning:

$effect bağımlılıkları (dependencies) otomatik tracking yapar — React'taki gibi manuel dependency array gerektirmez. Bu, "stale closure" hatalarını önler (prevents stale closure bugs).

5. $props Rune'u — Component Props

Svelte 4'te export let prop yazardık. Svelte 5'te $props kullanılır:

<!-- Eski (Svelte 4) -->
<script>
  export let title;
  export let count = 0;
</script>

<!-- Yeni (Svelte 5 — Runes) -->
<script lang="ts">
  let { title, count = 0 } = $props();
</script>

5.1 TypeScript ile Props

<script lang="ts">
  interface Props {
    title: string;
    count?: number;
    onSubmit: (value: string) => void;
  }

  let { title, count = 0, onSubmit }: Props = $props();
</script>

<h1>{title}</h1>
<button onclick={() => onSubmit('test')}>Gönder</button>

5.2 Rest Props (Geri Kalan Tüm Props)

<script lang="ts">
  let { class: className, ...rest } = $props();
</script>

<div class={className} {...rest}>...</div>

6. $bindable Rune'u — Two-Way Binding

Svelte 4'te child component'in parent state'ini değiştirmesi için bind: kullanılırdı. Svelte 5'te child component artık explicit olarak prop'un "bindable" olduğunu belirtmeli (must explicitly declare prop as bindable):

Child Component (Input.svelte)

<script lang="ts">
  let { value = $bindable(''), placeholder = '' } = $props();
</script>

<input bind:value {placeholder} />

Parent Component

<script>
  import Input from './Input.svelte';
  let name = $state('');
</script>

<Input bind:value={name} placeholder="Adınız" />
<p>Merhaba {name}</p>

7. Snippets — Slot'ların Modern Hali (Modern Slots)

Svelte 5'te slot'ların yerine snippets geldi (snippets replaced slots). Snippets, parametre alabilen yeniden kullanılabilir template parçalarıdır (reusable template parts that accept parameters).

<script>
  import Card from './Card.svelte';
</script>

<Card>
  {#snippet header()}
    <h2>Başlık (Title)</h2>
  {/snippet}

  {#snippet body(text)}
    <p>{text}</p>
  {/snippet}
</Card>

<!-- Card.svelte içinde -->
<script>
  let { header, body } = $props();
</script>

<div class="card">
  {@render header()}
  {@render body('Açıklama metni')}
</div>
✅ Avantaj:

Snippets, slot'lardan daha güçlü (more powerful than slots) — parametre alabilir, conditional render edilebilir, ve TypeScript ile tam type-safe.

8. Svelte 4'ten Svelte 5'e Migration Rehberi (Migration Guide)

8.1 Otomatik Migration Tool (Auto Migration Tool)

# SvelteKit projesinde
npx sv migrate svelte-5

# Standalone Svelte projesinde
npx svelte-migrate svelte-5

Bu tool şunları otomatik yapar:

  • export let xlet { x } = $props()
  • let count = 0 → reaktif kullanım varsa let count = $state(0)
  • $: derived = ...let derived = $derived(...)
  • $: { sideEffect() }$effect(() => { sideEffect() })

8.2 Manuel Migration Adımları

Adım 1: Paket Güncellemesi

npm install svelte@5
npm install -D @sveltejs/kit@latest @sveltejs/vite-plugin-svelte@latest

Adım 2: Component'leri Tek Tek Güncelle

Bir komponentte herhangi bir rune ($state, $derived, vs.) kullanırsanız o komponent runes mode'a geçer (component switches to runes mode). Aynı projede karışık kullanım mümkün.

Adım 3: Event Handler Değişikliği

<!-- Eski (Svelte 4) -->
<button on:click={handler}>Click</button>

<!-- Yeni (Svelte 5) -->
<button onclick={handler}>Click</button>

Standart DOM event isimlerinin on: öneki kaldırıldı (on: prefix removed for standard DOM events).

9. Performans Avantajları (Performance Benefits)

Bundle Size

Framework Min+gzip Runtime TodoMVC bundle
Svelte 4~12 KB~14 KB
Svelte 5~6 KB~10 KB
React 19~44 KB~50 KB
Vue 3.4~22 KB~28 KB
✅ Sonuç:

Svelte 5 hem React'tan hem Vue'dan çok daha küçük bundle üretir (much smaller bundle). Mobil ve edge senaryoları için ideal (ideal for mobile and edge).

10. Sık Karşılaşılan Hatalar (Common Pitfalls)

Hata 1: Destructuring Reactivity'yi Bozar

<script>
  let user = $state({ name: 'Ali' });

  // ❌ YANLIŞ — destructuring reactivity'yi koparır (breaks reactivity)
  let { name } = user;

  // ✅ DOĞRU — $derived ile bağla (bind with $derived)
  let name = $derived(user.name);
</script>

Hata 2: $effect İçinde State Mutasyonu (Infinite Loop!)

<script>
  let count = $state(0);

  // ❌ YANLIŞ — sonsuz döngü (infinite loop)
  $effect(() => {
    count++; // count değişir → effect tekrar çalışır → count tekrar değişir → ...
  });

  // ✅ DOĞRU — untrack ile koru
  import { untrack } from 'svelte';
  $effect(() => {
    untrack(() => count++);
  });
</script>

11. 📚 Kaynaklar ve Referanslar / Sources

Alesta Web olarak tüm örnekleri Svelte 5.10+ ile test ettik.

✅ Sonuç (Conclusion)

Svelte 5 Runes, framework'ün reactivity modelini modern bir çağa taşıyor (brings reactivity to a modern era). Daha tahmin edilebilir davranış (more predictable behavior), TypeScript ile daha iyi entegrasyon ve performans iyileştirmeleri ile birlikte gelen Runes, frontend geliştirme deneyimini bir üst seviyeye çıkarıyor.

Hızlı Karar Rehberi / Quick Decision Guide:

  • ✅ Yeni proje: Svelte 5 ile başlayın
  • ✅ Mevcut Svelte 4 projesi: Aşamalı migrate edin (gradual migration)
  • ✅ Performans/bundle hassas projeler: Svelte 5 ideal
  • ✅ TypeScript ağırlıklı projeler: Runes type-safe

Faydalı Linkler / Useful Links:

Alesta Web ekibi olarak Svelte 5 hakkında sorularınız için (for Svelte 5 questions) alestaweb.com'u ziyaret edebilirsiniz.

© 2026 AlestaWeb - Tüm hakları saklıdır.

Etiketler: Haberler