Introduction to Svelte stores
Tags: svelte, webdev
Published: 2021-04-09 16:24:54

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](https://svelte.dev/repl/4f59fa6b513e49fbab7987a17b5224aa?version=3.37.0)):

```javascript
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 {
  subscribe,
  add
}
```

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

```javascript
import { readable } from "svelte/store";
```

If you want to further, please see [this excellent example of readable stores](https://geoffrich.net/posts/svelte-prefers-reduced-motion-store/)

## Populate and update data

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

```HTML
<script>
   import actresses from "./actresses.js";
</script>

<pre>
{JSON.stringify($actresses)}
</pre>
```

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`:

```HTML
<script>
   import actresses from "./actresses.js";
	
   actresses.add({ "name": "AI", "oscars": 93 })
</script>

<pre>
{JSON.stringify($actresses, null, 2)}
</pre>
```

## 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`:

```HTML
<script> 
  import my_store from "./my_store.js"; // assuming you have a writable store in this file
	
  let handleClick = () => $my_store++;
</script>

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

<p>{$my_store}</p>
```

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

```HTML
{#if $my_store >  0 }
<p>{$my_store}</p>
{/if }
```

[Complete code is available in repl](https://svelte.dev/repl/d5e5aaa28dd6412d8138900401b086fa?version=3.37.0)

_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`](https://svelte.dev/docs#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.