$ effect ve Svelte 5'te Yaşam Döngüsü: Ne Zaman Kullanılmalı (ve Ne Zaman Kullanılmamalı)
Diğerlerinden daha fazla yanlış anlaşılan ve istismar edilen bir Svelte 5 Rune'u varsa, o da $effect.
React'tan geliyor, nerede useEffect ve çoğu zaman her çiviye bir çekiç ve doğal
bu modeli Svelte'de kopyalamaya çalışın. Ancak $effect farklı bir felsefesi var
kullanım kapsamı daha dardır ve bunu göz ardı etmek doğrudan çerçevenin en kötü anti-kalıplarına yol açar.
Bu kılavuz tam olarak ne yaptığını tanımlar $effecttakip mekanizması gibi
Otomatik dahili olarak çalışır, kullanılıp kullanılmayacağına karar vermenin altın kuralı nedir ve aşağıdakileri sağlar:
ana meşru kullanım senaryolarının somut örnekleri: analitik, WebSockets, kütüphanelerle entegrasyon
üçüncü taraf ve senkronize edin localStorage.
$ Effect'in Altın Kuralı
Yazmadan önce $effect, kendinize şunu sorun: "Mevcut durumdan bir şey mi hesaplıyorum?"
Cevabınız evet ise kullanın $derived. $effect ve gerçek yan etkiler için:
Kullanıcı arayüzü dışındaki dünyayla etkileşime giren işlemler (doğrudan DOM, ağ, depolama, zamanlayıcı,
üçüncü taraf kütüphaneleri).
$ effect Nasıl Çalışır: Otomatik İzleme
$effect DOM güncellendikten sonra bir işlevi yürütür. Özellik
temel ve bu sırasında okuduğu her $state ve $derived'i otomatik olarak izler
onun icrası ve bu bağımlılıklardan biri her değiştiğinde yeniden çalıştırılır.
Bağımlılıkları açıkça beyan etmek gerekli değildir.
<script lang="ts">
let count = $state(0);
let name = $state('Federico');
// Questo effect dipende da ENTRAMBI count e name
// perche li legge entrambi durante l'esecuzione
$effect(() => {
console.log(`${name} ha un contatore di ${count}`);
// Si ri-esegue quando count O name cambiano
});
// Questo effect dipende SOLO da count
$effect(() => {
document.title = `Contatore: ${count}`;
// Si ri-esegue SOLO quando count cambia
});
</script>
İzleme mekanizması aynı Proxy sistemini kullanır $state: yürütme sırasında
arasında $effect, reaktif bir değere her erişim günlüğe kaydedilir. Herhangi bir zaman
Bu değer değişikliklerinin her biri, efekt "kirli" olarak işaretlenir ve yeniden oynatılmak üzere planlanır.
Temizleme İşlevi
$effect önce çalışan bir temizleme işlevi döndürebilir.
Efektin bir sonraki yeniden yürütülmesinde ve bileşen söküldüğünde. Bunun için gereklidir
Zamanlayıcılar, abonelikler ve olay dinleyicileriyle bellek sızıntılarını önleyin:
<script lang="ts">
let wsUrl = $state('wss://api.example.com/stream');
let messages = $state<string[]>([]);
$effect(() => {
// Effect traccia wsUrl: si ri-esegue se l'URL cambia
const ws = new WebSocket(wsUrl);
ws.addEventListener('message', (event) => {
messages.push(event.data);
});
ws.addEventListener('error', (error) => {
console.error('WebSocket error:', error);
});
// Cleanup: chiude la connessione prima della prossima esecuzione
// e quando il componente viene smontato
return () => {
ws.close();
console.log('WebSocket chiuso');
};
});
</script>
Se wsUrl değişiklikler, Svelte 5 temizler (eski WS bağlantısını kapatır),
daha sonra efekti yeniden yürütür (yeni URL ile yeni bir bağlantı açar). Ve temiz bir desen
manuel yaşam döngüsü yönetimi gerektirmez.
Yaşam Döngüsü: $ effect vs onMount vs onDestroy
Svelte 5, Svelte 4'ün yaşam döngüsü işlevlerini korur (onMount, onDestroy,
vb.) geriye dönük uyumluluk için, ancak Runes daha tekdüze bir yaklaşım sunar:
<script lang="ts">
import { onMount, onDestroy } from 'svelte'; // Svelte 4 style
let data = $state(null);
// --- Svelte 4 pattern ---
onMount(async () => {
data = await fetchData();
});
// --- Svelte 5 equivalente con $effect ---
$effect(() => {
// $effect.root per effects che non dipendono da stato
// e si eseguono una sola volta (equivalente di onMount)
fetchData().then(result => {
data = result;
});
return () => {
// cleanup equivalente a onDestroy
};
});
// --- Svelte 5 per operazioni truly una-tantum ---
// Preferisci il blocco di codice nel componente
// o usa untrack() per evitare tracking accidentale
import { untrack } from 'svelte';
$effect(() => {
// untrack impedisce il tracking di initialValue
const initial = untrack(() => data);
console.log('Valore iniziale (non tracciato):', initial);
// count E tracciato perche e fuori da untrack
console.log('Count corrente:', count);
});
</script>
$ effect'in Meşru Kullanım Durumları
İşte ana senaryolar $effect ve doğru seçim:
1. localStorage ile senkronizasyon
<script lang="ts">
// Leggi il valore iniziale da localStorage (fuori da $effect)
let theme = $state<'light' | 'dark'>(
(localStorage.getItem('theme') as 'light' | 'dark') ?? 'light'
);
// Sincronizza le modifiche a localStorage
$effect(() => {
localStorage.setItem('theme', theme);
document.documentElement.setAttribute('data-theme', theme);
});
</script>
<button onclick={() => theme = theme === 'light' ? 'dark' : 'light'}>
Toggle theme
</button>
2. Analitik ve İzleme
<script lang="ts">
const { pageId, userId }: { pageId: string; userId?: string } = $props();
// Traccia la visualizzazione di pagina quando pageId cambia
$effect(() => {
// Sia pageId che userId sono tracciati
analytics.track('page_view', {
page: pageId,
user: userId ?? 'anonymous',
timestamp: new Date().toISOString()
});
});
</script>
3. Üçüncü Taraf DOM Kütüphaneleriyle Entegrasyon
<script lang="ts">
import Chart from 'chart.js/auto';
let canvasEl: HTMLCanvasElement;
let chartData = $state({ labels: [], datasets: [] });
let chartInstance: Chart | null = null;
$effect(() => {
// Prima esecuzione: crea il chart
if (!chartInstance) {
chartInstance = new Chart(canvasEl, {
type: 'bar',
data: chartData
});
} else {
// Ri-esecuzioni: aggiorna i dati
chartInstance.data = chartData;
chartInstance.update();
}
return () => {
// Cleanup: distruggi il chart
chartInstance?.destroy();
chartInstance = null;
};
});
</script>
<canvas bind:this={canvasEl}></canvas>
4. Kesişme Gözlemcisi (Tembel Yükleme, Kaydırmada Animasyonlar)
<script lang="ts">
let element: HTMLElement;
let isVisible = $state(false);
let hasBeenVisible = $state(false);
$effect(() => {
const observer = new IntersectionObserver(
(entries) => {
isVisible = entries[0].isIntersecting;
if (isVisible) hasBeenVisible = true;
},
{ threshold: 0.1 }
);
observer.observe(element);
return () => observer.disconnect();
});
</script>
<div
bind:this={element}
class:visible={isVisible}
class:animated={hasBeenVisible}
>
Contenuto che appare con animazione
</div>
Anti-Desen: Hesaplamalar için $ effect kullanmayın
En yaygın anti-desen $effect ve bunu başka bir şeyden türetilen durumu güncellemek için kullanın
devlet. Bu, verimsiz ve potansiyel olarak sonsuz güncelleme döngüleri yaratır:
<script lang="ts">
let items = $state([1, 2, 3, 4, 5]);
let total = $state(0); // SBAGLIATO: non dovrebbe essere $state
// ANTI-PATTERN: usare $effect per calcolare un valore derivato
$effect(() => {
total = items.reduce((s, i) => s + i, 0);
// Questo crea: items cambia -> effect corre -> total cambia ->
// potenziali altri effects si ri-eseguono inutilmente
});
// CORRETTO: usare $derived
const totalCorrect = $derived(items.reduce((s, i) => s + i, 0));
</script>
<script lang="ts">
let searchQuery = $state('');
let filteredUsers = $state([]); // SBAGLIATO
// ANTI-PATTERN: filtrare con $effect
$effect(() => {
filteredUsers = users.filter(u =>
u.name.toLowerCase().includes(searchQuery.toLowerCase())
);
});
// CORRETTO: $derived
const filteredUsersCorrect = $derived(
users.filter(u =>
u.name.toLowerCase().includes(searchQuery.toLowerCase())
)
);
</script>
$efekt ve Sonsuz Döngüler
Klasik bir hata ve içinde düzenleme $effect







