[Svelte Series 6] Fundamentals of Sharing State with Stores

한국어 버전

Putting a single form on the screen is not enough to ship a service. You need a concept that lets multiple components watch the same data, and in Svelte that concept is the store.

Key terms

  1. Store: A Svelte object that holds a value and lets components subscribe to it so they can share state without passing props through every layer.
  2. Subscription: The act of observing a store so a callback runs whenever the underlying value changes.
  3. writable/readable: Helper functions that create stores; the former can be read and written, while the latter exposes a read-only value.
  4. derived: A helper that computes new values from existing stores, useful for counters, badges, or other calculated slices of data.

Core ideas

A store is an object that stores a value and exposes a subscribe method. Any component that subscribes sees the same state at the same moment, even when no props are passed between them. A subscription is simply a callback that re-runs when the value changes. writable stores cover the common read/write use case, readable hides mutations from external code, and derived lets you compute new values out of existing ones. Combined, they make sure a header badge, dashboard card, and modal list all stay in sync.

Important Svelte store concepts

  • Store definition files obey the run-once-per-module rule. When src/lib/stores/*.js is imported, the code executes once on either the server or the client, and the exported store instance is reused everywhere.
  • Prefixing a store with $ inside a component ($notifications) automatically subscribes and unsubscribes. The $ syntax is unavailable inside <script context="module"> blocks or server files, so call store.subscribe manually there.
  • A store is just a JavaScript object. It cannot access the database directly. Fetch data in load functions or form actions first, then populate the store so the client cannot bypass server safeguards.

Code examples

Let’s wire up a notification center that multiple components can consume.

// src/lib/stores/notifications.js

const base = writable([]);

export const notifications = {
  subscribe: base.subscribe,
  push(message) {
    base.update((list) => [...list, { id: crypto.randomUUID(), message }]);
  },
  remove(id) {
    base.update((list) => list.filter((item) => item.id !== id));
  }
};

export const unreadCount = derived(base, ($list) => $list.length);

Inside a component you can import { notifications, unreadCount } and read $notifications or $unreadCount immediately. Calling push or remove updates every subscriber—dashboard cards, header badges, and modal lists all change together.

Why it matters

School apps often surface the same data in multiple places: assignment alerts must appear in both a card and a header, or attendance must show up in a list and a popup. Without stores, you end up with brittle prop chains. Stores centralize data flow so that later, when you attach API calls, loading and error flags can also be shared in one place.

Practice checklist

  • Follow along by building the notifications and unreadCount stores and subscribe to them from two components.
  • Extend the pattern with a derived store that returns only the first three unread messages.
  • Debug by double-checking $store prefixes and ensuring you clean up the function returned from subscribe when using manual subscriptions.
  • Completion criteria: adding or removing a notification updates both the header and the list at the same time.

Wrap-up

When stores sit at the center, state management stays simple even as screens multiply. In the next installment we’ll connect these stores to page-level data loading.

💬 댓글

이 글에 대한 의견을 남겨주세요