Effects

Loading concept...

🎭 Svelte Effects: Your App’s Automatic Helpers

The Magic Story of Effects

Imagine you have a magic helper who watches over your toys. Every time you move a toy, this helper automatically does something helpful—like turning on a light when you put a car in the garage, or playing music when you set a doll on the dance floor.

In Svelte, effects are these magic helpers. They watch your data and automatically do things when that data changes!


🌟 What Are Effects?

Think of your app like a house:

  • State ($state) = your stuff (toys, books, snacks)
  • Effects ($effect) = automatic helpers that respond when stuff changes
let count = $state(0);

$effect(() => {
  console.log('Count changed to:', count);
});

Every time count changes, the effect runs automatically!


📦 The $effect Rune

The $effect rune is your main helper. It runs after Svelte updates the screen.

Simple Example: A Light Switch

<script>
  let isOn = $state(false);

  $effect(() => {
    if (isOn) {
      document.title = '💡 Light ON';
    } else {
      document.title = '🌙 Light OFF';
    }
  });
</script>

<button onclick={() => isOn = !isOn}>
  Toggle Light
</button>

What happens:

  1. You click the button
  2. isOn changes
  3. Svelte updates the screen
  4. The effect runs and changes the page title

⚡ The $effect.pre Rune

Sometimes you need your helper to work before the screen updates. That’s $effect.pre!

The Story

Imagine you’re painting a wall.

  • $effect = takes a photo after you finish painting
  • $effect.pre = prepares the camera before you start

When to Use It

Use $effect.pre when you need to:

  • Measure something before it changes
  • Save a scroll position
  • Capture “before” values
<script>
  let messages = $state([]);
  let container;
  let shouldScroll = false;

  $effect.pre(() => {
    // Check BEFORE new messages appear
    if (container) {
      const atBottom =
        container.scrollTop +
        container.clientHeight >=
        container.scrollHeight - 10;
      shouldScroll = atBottom;
    }
  });

  $effect(() => {
    // Scroll AFTER messages appear
    if (shouldScroll && container) {
      container.scrollTop =
        container.scrollHeight;
    }
  });
</script>

🌳 The $effect.root Function

Normally, effects live inside your component. When the component disappears, effects stop automatically.

But what if you need an effect that lives outside a component? That’s $effect.root!

The Story

Think of a regular effect like a pet fish in a bowl. When you clean the bowl (component unmounts), the fish goes too.

$effect.root is like having a fish tank in the living room—it stays even when you leave your bedroom!

Example: A Shared Timer

<script>
  import { createTimer } from './timer.js';

  const timer = createTimer();
</script>

// timer.js
export function createTimer() {
  let seconds = $state(0);

  const cleanup = $effect.root(() => {
    const interval = setInterval(() => {
      seconds++;
    }, 1000);

    return () => clearInterval(interval);
  });

  return {
    get seconds() { return seconds; },
    stop: cleanup
  };
}

Key Point: You must call cleanup() yourself when done!


🧹 Effect Cleanup

What if your effect starts something that needs to stop later? Like turning on a fan—you need to turn it off when you leave!

How Cleanup Works

Return a function from your effect. Svelte calls it:

  • Before the effect runs again
  • When the component is destroyed
<script>
  let isActive = $state(true);

  $effect(() => {
    if (!isActive) return;

    // Start something
    const timer = setInterval(() => {
      console.log('Tick!');
    }, 1000);

    // Cleanup function
    return () => {
      console.log('Cleaning up!');
      clearInterval(timer);
    };
  });
</script>

Visual Flow

graph TD A[Effect Runs] --> B[Do Your Work] B --> C[Return Cleanup Function] C --> D{Data Changes?} D -->|Yes| E[Run Cleanup First] E --> A D -->|No| F{Component Destroyed?} F -->|Yes| G[Run Cleanup & Stop] F -->|No| D

🔗 Effect Dependencies

Effects are smart! They automatically know what data they use.

The Magic Detection

<script>
  let name = $state('Alice');
  let age = $state(10);

  $effect(() => {
    // Only uses 'name'
    console.log('Hello', name);
  });
  // Runs when: name changes
  // Ignores: age changes
</script>

How It Works

Svelte watches which $state values you read inside the effect. Only those become dependencies!

Be Careful!

// ❌ This won't track anything!
$effect(() => {
  setTimeout(() => {
    console.log(count); // Read inside timeout
  }, 1000);
});

// ✅ This tracks correctly!
$effect(() => {
  const current = count; // Read immediately
  setTimeout(() => {
    console.log(current);
  }, 1000);
});

Rule: Read your reactive values at the top of your effect, not inside callbacks!


🔍 The $inspect Rune

Want to spy on your data? $inspect is your detective tool!

Basic Usage

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

  $inspect(user);
  // Logs whenever user changes!
</script>

The .with() Method

Want custom logging?

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

  $inspect(score).with((type, value) => {
    if (type === 'update') {
      console.log('🎯 Score is now:', value);
    }
  });
</script>

Types of Changes

  • 'init' = first time the value is set
  • 'update' = value changed after that

Pro Tip: Debugging Made Easy

<script>
  let items = $state([]);

  // Pause debugger when items change
  $inspect(items).with(() => {
    debugger;
  });
</script>

🎯 Quick Comparison

Rune When It Runs Use Case
$effect After DOM updates Most effects
$effect.pre Before DOM updates Measure/capture
$effect.root Manual control Outside components
$inspect On any change Debugging

🌈 Real-World Example

Let’s build a Dark Mode Toggle with all our knowledge!

<script>
  let isDark = $state(false);

  // Debug mode changes
  $inspect(isDark);

  // Apply theme after render
  $effect(() => {
    document.body.classList.toggle(
      'dark-mode',
      isDark
    );

    // Save preference
    localStorage.setItem(
      'theme',
      isDark ? 'dark' : 'light'
    );

    // Cleanup: restore original
    return () => {
      document.body.classList
        .remove('dark-mode');
    };
  });
</script>

<button onclick={() => isDark = !isDark}>
  {isDark ? '☀️ Light' : '🌙 Dark'}
</button>

🎉 You Did It!

You now understand Svelte’s effect system:

  • $effect — runs after screen updates
  • $effect.pre — runs before screen updates
  • $effect.root — manual lifecycle control
  • ✅ Cleanup — return a function to clean up
  • ✅ Dependencies — auto-detected from reads
  • $inspect — debugging helper

Remember: Effects are your automatic helpers. Tell them what to watch, and they’ll do the work!

Loading story...

No Story Available

This concept doesn't have a story yet.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Interactive Content

This concept doesn't have interactive content yet.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Cheatsheet Available

This concept doesn't have a cheatsheet yet.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Quiz Available

This concept doesn't have a quiz yet.