Sometimes you need to read reactive values without creating dependencies. That's what untrack is for.
The Problem: Unwanted Re-runs
svelte<script> let count = $state(0); let logCount = $state(0); // ❌ This runs whenever count OR logCount changes! $effect(() => { console.log(`Count changed to ${count}`); logCount++; // Reading logCount creates a dependency }); </script>
This creates an infinite loop:
- count changes → effect runs
- effect increments logCount
- logCount changed → effect runs
- effect increments logCount...
The Solution: untrack
svelte<script> import { untrack } from 'svelte'; let count = $state(0); let logCount = $state(0); // ✅ Only re-runs when count changes $effect(() => { console.log(`Count changed to ${count}`); // Read logCount without tracking it untrack(() => { logCount++; }); }); </script>
When to Use untrack
Use for:
- Logging/analytics that shouldn't trigger re-runs
- Reading values for comparison without subscribing
- Breaking potential infinite loops
Don't overuse:
- If you're using
untrackeverywhere, reconsider your data flow
Example: Analytics
svelte<script> import { untrack } from 'svelte'; let searchTerm = $state(''); let searchHistory = $state([]); $effect(() => { if (searchTerm.length > 2) { // We want to track searchTerm // but NOT searchHistory (would cause re-run when we push) untrack(() => { searchHistory = [...searchHistory, searchTerm]; }); } }); </script>