DEV Community

Alex Spinov
Alex Spinov

Posted on

Svelte 5 Runes Has a Free API You're Not Using

Svelte 5 introduced Runes — a new reactivity system that's simpler, more powerful, and works everywhere (not just .svelte files). Most developers are still writing Svelte 4 code.

The Free APIs You're Missing

1. $state — Universal Reactive State

<script>
let count = $state(0);
let user = $state({ name: "Alice", age: 30 });
let items = $state(["apple", "banana"]);

// Deep reactivity — mutations trigger updates!
function birthday() {
  user.age += 1; // Just mutate — Svelte tracks it
}

function addItem() {
  items.push("cherry"); // Array mutations work too!
}
</script>

<button onclick={() => count++}>{count}</button>
<p>{user.name} is {user.age}</p>
Enter fullscreen mode Exit fullscreen mode

2. $derived — Computed Values

<script>
let items = $state([{ price: 10, qty: 2 }, { price: 5, qty: 3 }]);

let total = $derived(items.reduce((sum, i) => sum + i.price * i.qty, 0));
let itemCount = $derived(items.length);
let expensive = $derived(items.filter(i => i.price > 7));

// $derived.by for complex computations
let summary = $derived.by(() => {
  const subtotal = items.reduce((s, i) => s + i.price * i.qty, 0);
  const tax = subtotal * 0.1;
  return { subtotal, tax, total: subtotal + tax };
});
</script>
Enter fullscreen mode Exit fullscreen mode

3. $effect — Side Effects Done Right

<script>
let query = $state("");
let results = $state([]);

$effect(() => {
  // Runs when query changes (auto-tracked!)
  const controller = new AbortController();
  fetch(`/api/search?q=${query}`, { signal: controller.signal })
    .then(r => r.json())
    .then(data => results = data);

  // Cleanup function — like useEffect return
  return () => controller.abort();
});

// Pre-effect (runs before DOM update)
$effect.pre(() => {
  console.log("About to update DOM with:", results.length, "results");
});
</script>
Enter fullscreen mode Exit fullscreen mode

4. $props — Component Props

<!-- Button.svelte -->
<script>
let { variant = "primary", size = "md", onclick, children, ...rest } = $props();
</script>

<button class="btn btn-{variant} btn-{size}" {onclick} {...rest}>
  {@render children()}
</button>
Enter fullscreen mode Exit fullscreen mode

5. Snippets — Reusable Template Blocks

<script>
let items = $state(["A", "B", "C"]);
</script>

{#snippet row(item, index)}
  <tr>
    <td>{index + 1}</td>
    <td>{item}</td>
    <td><button onclick={() => items.splice(index, 1)}>Delete</button></td>
  </tr>
{/snippet}

<table>
  {#each items as item, i}
    {@render row(item, i)}
  {/each}
</table>
Enter fullscreen mode Exit fullscreen mode

Getting Started

npm create svelte@latest my-app
cd my-app && npm install && npm run dev
Enter fullscreen mode Exit fullscreen mode

Need data from any website delivered as clean JSON? I build production web scrapers that handle anti-bot, proxies, and rate limits. 77 scrapers running in production. Email me: Spinov001@gmail.com

Check out my awesome-web-scraping list for the best scraping tools and resources.

Top comments (0)