DEV Community


Posted on • Updated on

Introduction to Svelte stores

Svelte is a crazy good compiler that generates boosted vanilla JavaScript.

It's readable and straightforward, and it has an unusual approach for common patterns you might dig in.

State management in Svelte

Svelte does a lot of magic behind the scene. I usually don't consider "magic" as a good thing in code, but, IMHO, it makes sense here.

I like the philosophy: it does not create elements when it's not needed. Sometimes, it breaks nodes into separate nodes for more efficient updates.

Besides, the compiler has a particular way to handle the app state. It provides pretty cool bindings to manage state within the component hierarchy.

However, not everything is a parent-child relationship. You often need global data. That's when stores can be helpful.

Stores and subscription in general

Stores store values. They are objects.

Stores necessarily implement a subscribe() method. Every time a value changes, the subscribe() method notifies all elements connected to the store. They can also have a set() method to add values.

Getting started with Svelte stores

Svelte has writable and readable stores. Readable stores are read-only, unlike writable stores.

Let's write a store in a file called actresses.js (you can read the whole demo code in this repl):

import { writable } from "svelte/store";

let actresses = [
  { "name": "Naomi Watts", "oscars": 0 },
  { "name": "Scarlett Johansson", "oscars": 0 },
  { "name": "Charlize Theron", "oscars": 1 },

let { subscribe, update } = writable(actresses);

let add = actress => update(actresses => {
  return [...actresses, actress];

export default {
Enter fullscreen mode Exit fullscreen mode

Not all stores should be writable. If it does not make sense, don't let any component set/update values in your store:

import { readable } from "svelte/store";
Enter fullscreen mode Exit fullscreen mode

If you want to further, please see this excellent example of readable stores

Populate and update data

To use our store of actresses, it's pretty straightforward:

   import actresses from "./actresses.js";

Enter fullscreen mode Exit fullscreen mode

We use the syntactic sugar $. Svelte provides this handy hack to bind things quickly, but we'll see that later in the post.

If you need to update something, you can leverage the benefits of writable:

   import actresses from "./actresses.js";

   actresses.add({ "name": "AI", "oscars": 93 })

{JSON.stringify($actresses, null, 2)}
Enter fullscreen mode Exit fullscreen mode

Automatic subscription and $

Adding $ before any Svelte variable makes your variable an object with a subscribe() and an unsubscribe() method by default.

This way, you don't have to write the same code repeatedly. The following code does not need to handle any mount/unmount event. It's automagic:

  import my_store from "./my_store.js"; // assuming you have a writable store in this file

  let handleClick = () => $my_store++;

<button on:click={ handleClick }>Click</button>

Enter fullscreen mode Exit fullscreen mode

And you can add an "if block" to conditionally display the counter:

{#if $my_store >  0 }
{/if }
Enter fullscreen mode Exit fullscreen mode

Complete code is available in repl

N.B: Please make sure you use $ for stores only, not DOM references. Svelte does not allow this kind of usage.

Derived stores

Svelte allows for using values from one or several stores inside another store.

It's called derived, and it might be helpful when you don't want to update values manually when other state changes.

It could prevent unnecessary complexity in individual stores. Honestly, I never had to use it, but it's available if you need it.

Wrap up

The need for app-wide data, outside of the component hierarchy, is not uncommon, and Svelte stores are ready for that usage.

Cherry on top, Svelte allows creating and using stores effortlessly thanks to an auto-subscribe mechanism.

Top comments (0)