S SvelteKurs
M7 · State-Management

Stores

Der klassische Svelte-Weg für geteilten Zustand: ein Objekt mit .subscribe, das du im Markup bequem mit dem $-Präfix liest.

Was ist ein Store?

Ein Store ist einfach ein Objekt mit einer .subscribe-Methode. Er hält einen Wert, und jeder Interessent kann sich benachrichtigen lassen, wenn sich dieser Wert ändert. Weil ein Store ein ganz normaler JavaScript-Wert ist, kannst du ihn aus einem Modul exportieren und in beliebig vielen Komponenten verwenden — genau das macht ihn zum Werkzeug für komponentenübergreifenden Zustand.

stores.js js
import { writable } from 'svelte/store';

// Ein Store ist ein Objekt mit einer .subscribe-Methode.
export const zaehler = writable(0);

Svelte bringt drei Fabrik-Funktionen mit: writable (les- und schreibbar), readable (nur lesbar) und derived (aus anderen Stores abgeleitet).

Das $-Präfix: automatische Subscription

Der eigentliche Komfort liegt im Markup: Schreibst du einem Store-Namen ein $ voran, abonniert Svelte den Store automatisch, liest seinen aktuellen Wert und meldet sich beim Zerstören der Komponente sauber wieder ab. Kein manuelles subscribe/unsubscribe nötig.

Zaehler.svelte svelte
<script>
  import { zaehler } from './stores.js';
</script>

<!-- $-Präfix = automatische Subscription im Markup -->
<p>Wert: {$zaehler}</p>
<button onclick={() => $zaehler++}>+1</button>

💡 $store ist Lesen UND Schreiben

{$zaehler} liest den Wert. Eine Zuweisung wie $zaehler++ oder $zaehler = 5 im Script ruft intern .set(...) auf. Das $-Präfix funktioniert nur in .svelte-Dateien — in normalen .js/.ts-Dateien nutzt du die Methoden direkt.

set, update, subscribe und get

Außerhalb des Markups arbeitest du mit den Methoden des Stores:

js
import { get } from 'svelte/store';

zaehler.set(10);                 // Wert direkt setzen
zaehler.update((n) => n + 1);    // Wert aus dem alten berechnen

const wert = get(zaehler);       // einmalig auslesen (ohne Subscription)

// Manuell abonnieren — gibt eine unsubscribe-Funktion zurück:
const stop = zaehler.subscribe((n) => console.log('neu:', n));
stop(); // wieder abmelden (im Markup macht das $ automatisch)
  • .set(wert) — setzt einen neuen Wert.
  • .update(fn) — berechnet den neuen Wert aus dem alten (z. B. Hochzählen).
  • .subscribe(fn) — ruft fn sofort und bei jeder Änderung auf; gibt eine Funktion zum Abmelden zurück.
  • get(store) — liest den Wert genau einmal aus (praktisch, aber sparsam einsetzen: kein reaktives Abonnement).

Live ausprobieren

Die folgende Demo nutzt echte Stores aus dieser Seite: ein writable namens zaehler und ein daraus abgeleitetes derived namens verdoppelt. Beide werden im Markup mit $ gelesen.

▶ writable + derived · Interaktiv
0

$zaehler = 0 · abgeleitet $verdoppelt = 0

readable & derived

Ein readable ist ein Store, den nur seine eigene Start-Funktion füttert — von außen kannst du ihn ausschließlich lesen. Ideal für Werte, die aus einer Quelle „ticken" (Uhr, WebSocket, Geolocation):

js
import { readable } from 'svelte/store';

// readable: von außen nur lesbar. Der zweite Parameter ist eine
// Start-Funktion; sie bekommt "set" und gibt eine Aufräum-Funktion zurück.
export const uhrzeit = readable(new Date(), (set) => {
  const id = setInterval(() => set(new Date()), 1000);
  return () => clearInterval(id); // beim letzten Abmelden aufräumen
});

Ein derived-Store berechnet seinen Wert automatisch aus einem oder mehreren anderen Stores neu — vergleichbar mit $derived bei den Runes, nur eben auf Store-Ebene:

js
import { writable, derived } from 'svelte/store';

export const preis = writable(100);
export const menge = writable(3);

// Aus einem Store ableiten:
export const doppelt = derived(preis, ($preis) => $preis * 2);

// Aus mehreren Stores ableiten (Array als erstes Argument):
export const summe = derived(
  [preis, menge],
  ([$preis, $menge]) => $preis * $menge
);

Einordnung zu Rails

🛤️ Rails-Vergleich: geteilter, reaktiver Zustand im Client

In Rails lebt „Zustand" typischerweise in Session, Datenbank oder Redis und wird pro Request frisch geladen — ein Snapshot, der bis zur nächsten Anfrage eingefroren ist. Ein Store ist das clientseitige Gegenstück, aber reaktiv: Der Wert lebt im Browser weiter, und jede Komponente, die $store liest, aktualisiert sich sofort bei einer Änderung — ganz ohne neuen Request oder Reload.

Rails ruby
# Rails: ein Wert, der prozessweit "lebt" und beobachtet wird,
# ist hier eher untypisch — Zustand steckt in Session/DB/Redis
# und wird pro Request frisch geladen.
class CartController < ApplicationController
  def show
    @total = current_cart.items.sum(&:price) # Snapshot pro Request
  end
end

Zusammenfassung

💡 Das Wichtigste

  • writable/readable/derived erzeugen Stores; ein Store ist ein Objekt mit .subscribe.
  • Im Markup liest du mit $store (Auto-Subscription inkl. Aufräumen).
  • .set/.update/.subscribe steuern den Store im Code; get(store) liest einmalig.
  • Stores sind heute besonders für async/„RxJS-artige" Fälle und die $app/stores von SvelteKit relevant — für simplen geteilten State sind oft Runes-Module (nächste Lektion) die schlankere Wahl.

🎯 Probier es selbst

Ergänze einen zweiten writable-Store faktor und ein derived([zaehler, faktor], ([z, f]) => z * f). Zeige das Ergebnis im Markup mit $ an und beobachte, wie es auf Änderungen beider Stores reagiert.