Skip to main content
Svelte Fundamentals
CHAPTER 10 Beginner

Svelte Stores

Updated: May 18, 2026
5 min read

# CHAPTER 10

Svelte Stores

1. Chapter Introduction

When multiple components need access to the same state — a user's shopping cart, auth status, or theme preference — passing props becomes impractical. Svelte Stores are reactive containers that any component can subscribe to, regardless of their position in the component tree. They are simpler than Redux or Vuex and built right into Svelte's runtime.

2. Learning Objectives

  • Create writable, readable, and derived stores.
  • Use the $store auto-subscription syntax.
  • Update stores from any component.
  • Build a complete shopping cart using stores.

3. Writable Store

javascript
1234567
// src/lib/stores/cart.js
import { writable } from 'svelte/store';

// Create a writable store with initial value
export const cart = writable([]);
export const count = writable(0);
export const theme = writable('light');
svelte
1234567
<!-- CartIcon.svelte -->
<script>
  import { cart } from &#039;$lib/stores/cart.js';
  // $cart auto-subscribes AND auto-unsubscribes!
</script>

<span>🛒 {$cart.length} items</span>
svelte
12345678910111213
<!-- AddToCartButton.svelte -->
<script>
  import { cart } from &#039;$lib/stores/cart.js';

  export let product;

  function addToCart() {
    cart.update(items => [...items, product]);
    // OR: cart.set([...$cart, product]); // using .set()
  }
</script>

<button on:click={addToCart}>Add to Cart</button>

4. Store Methods: set, update, subscribe

javascript
1234567891011121314
import { count } from &#039;./stores.js&#039;;

// .set() — replace the value entirely
count.set(0);

// .update() — apply a function to current value
count.update(n => n + 1);

// .subscribe() — manually subscribe (remember to unsubscribe!)
const unsubscribe = count.subscribe(value => {
  console.log(&#039;Count is now:&#039;, value);
});

// In a component, use $count auto-subscription instead!

5. The $store Auto-Subscription

The $ prefix is Svelte's magic syntax for store auto-subscription — it subscribes when the component mounts and unsubscribes when it's destroyed:
svelte
12345678910111213141516
<script>
  import { cart, theme } from &#039;$lib/stores/cart.js';

  function clearCart() {
    cart.set([]);
  }
</script>

<!-- $cart automatically reads the current store value -->
<p>Items in cart: {$cart.length}</p>
<p>Current theme: {$theme}</p>

<!-- $store in event handlers -->
<button on:click={() => theme.set($theme === &#039;light' ? 'dark' : 'light')}>
  Toggle Theme
</button>

6. Readable Store (Read-Only)

javascript
12345678910111213
import { readable } from &#039;svelte/store&#039;;

// A clock that updates every second
export const time = readable(new Date(), function start(set) {
  const interval = setInterval(() => {
    set(new Date());
  }, 1000);

  // Cleanup when last subscriber unsubscribes
  return function stop() {
    clearInterval(interval);
  };
});
svelte
12345
<script>
  import { time } from &#039;$lib/stores/time.js';
</script>

<p>Current time: {$time.toLocaleTimeString()}</p>

7. Derived Store

javascript
1234567891011121314151617181920212223242526
import { derived } from &#039;svelte/store&#039;;
import { cart } from &#039;./cart.js&#039;;

// Derived from cart store
export const cartTotal = derived(cart, $cart =>
  $cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
);

export const cartItemCount = derived(cart, $cart =>
  $cart.reduce((sum, item) => sum + item.quantity, 0)
);

// Derived from multiple stores
import { readable } from &#039;svelte/store&#039;;
import { userPreferences } from &#039;./userStore.js&#039;;

export const greeting = derived(
  [time, userPreferences],
  ([$time, $prefs]) => {
    const hour = $time.getHours();
    const name = $prefs.name || &#039;Guest&#039;;
    if (hour < 12) return `Good morning, ${name}!`;
    if (hour < 17) return `Good afternoon, ${name}!`;
    return `Good evening, ${name}!`;
  }
);

8. Mini Project: Shopping Cart Store

javascript
123456789101112131415161718192021222324252627282930
// src/lib/stores/cartStore.js
import { writable, derived } from &#039;svelte/store&#039;;

export const cartItems = writable([]);

export const cartTotal = derived(cartItems, $items =>
  $items.reduce((sum, item) => sum + item.price * item.qty, 0)
);

export const cartCount = derived(cartItems, $items =>
  $items.reduce((sum, item) => sum + item.qty, 0)
);

export function addToCart(product) {
  cartItems.update(items => {
    const existing = items.find(i => i.id === product.id);
    if (existing) {
      return items.map(i => i.id === product.id ? {...i, qty: i.qty + 1} : i);
    }
    return [...items, { ...product, qty: 1 }];
  });
}

export function removeFromCart(id) {
  cartItems.update(items => items.filter(i => i.id !== id));
}

export function clearCart() {
  cartItems.set([]);
}
svelte
12345678910111213141516171819202122232425
<!-- CartSummary.svelte -->
<script>
  import { cartItems, cartTotal, cartCount, removeFromCart, clearCart } from &#039;$lib/stores/cartStore.js';
</script>

<div class="cart">
  <h2>Shopping Cart ({$cartCount} items)</h2>

  {#each $cartItems as item (item.id)}
    <div class="cart-item">
      <span>{item.name}</span>
      <span>×{item.qty}</span>
      <span>${(item.price * item.qty).toFixed(2)}</span>
      <button on:click={() => removeFromCart(item.id)}>✕</button>
    </div>
  {:else}
    <p>Your cart is empty.</p>
  {/each}

  {#if $cartItems.length > 0}
    <div class="total">Total: ${$cartTotal.toFixed(2)}</div>
    <button on:click={clearCart}>Clear Cart</button>
    <button class="checkout">Checkout</button>
  {/if}
</div>

9. Common Mistakes

  • Using .subscribe() in components without unsubscribing: Always use $store auto-subscription in components. Only use .subscribe() in plain JS files, and remember to call unsubscribe() when done.
  • Storing non-serializable values: Avoid storing DOM nodes, class instances, or functions in stores. Store plain data objects.

10. MCQs

Question 1

What function creates a modifiable Svelte store?

Question 2

What does the $ prefix do before a store name in a template?

Question 3

What method completely replaces a store's value?

Question 4

What method applies a function to update a store's value?

Question 5

What store type is read-only and defined with a setup/teardown function?

Question 6

What store type computes its value from one or more other stores?

Question 7

What happens to the readable store's cleanup function?

Question 8

Where should Svelte store definitions typically live?

Question 9

Can two completely unrelated components read and update the same store?

Question 10

What is the difference between local state and a store?

11. Interview Questions

  • Q: Compare Svelte Stores to Redux. What makes Svelte Stores simpler?
  • Q: Explain the difference between writable, readable, and derived stores.

12. Summary

Svelte Stores are the simplest global state management solution in any frontend framework. writable for mutable state, readable for external data sources, derived for computed values. The $store auto-subscription syntax eliminates manual subscribe/unsubscribe lifecycle management, making reactive global state feel as natural as local component state.

13. Next Chapter Recommendation

In Chapter 11: Forms and User Input, we master two-way binding with bind:value, form validation, and handling complex user input scenarios.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·