Svelte

Svelte Stores & Derived State

Topics:

This course has been updated! We now recommend you take the Svelte Fundamentals course.

Check out a free preview of the full Svelte course:
The "Stores & Derived State" Lesson is part of the full, Svelte course featured in this preview video. Here's what you'd learn in this lesson:

Rich demonstrates Svelte Stores which is an object with a subscribe method that allows interested parties to be notified whenever the store value changes. Rich also demonstrates the ability to create a store whose value is based on the value of one or more other stores with derived.

Get Unlimited Access Now

Transcript from the "Stores & Derived State" Lesson

[00:00:00]
>> So far, all of the state that we've been dealing with has been state that belongs to specific components. And if we need to pass it around between components, then we use props, and we use bindings and we use events. But that's not always what you want. Sometimes you have state that doesn't really belong to a specific component.

[00:00:18] Sometimes it's global state, like an object representing the current user and things like that. And we need to have a way of representing those outside the components. And for that we have the concept of stores. The store is pretty simple. It's just an object with a subscribe method.

[00:00:39] And it's not even Svelte specific. It's something that you could use in any application, as we'll see. But it does have a specific importance to Svelte. So here's our file, stores.js. We're importing writable from Svelte/Store. Not the main Svelte package, but the the Svelte/Store package, which is one of a number of packages that live inside the Svelte namespace.

[00:01:04] And then we're initializing it with 0, and that becomes our count store. And then we're importing that count store into each of these components' app. Decrementer, incrementer, and resetter. And as the name suggests, the job of each of these components is to increment, decrement, or reset the value of that store.

[00:01:32] So inside the increment, the component. Let's change the value of the store by calling count.update And then we're gonna pass in a handler that takes the current value and returns the new value. That's the job of the update method. And now when I click the + button, the value of the count increases.

[00:02:00] And the way that we're getting that value into App is by subscribing to it. So here we're declaring count value. And then we're calling count.subscribe, and giving it a callback. Which takes the value, the current value which is the callback that runs every time the value of count changes, as well as when you first subscribe to it.

[00:02:22] And then it's passing that value back up to count value, which is then referenced inside the marker. And so that's how clicking this button affects the contents of the h1. And if you thinking, that's quite a lot of boilerplate, you're not wrong. And we're gonna get to that.

[00:02:41] We're gonna wire up the decrementer first. Same thing, count, update, n, n -1. And now we can press the + button and the- button. Finally, in the re-setter, we don't care about the current value, we're always just gonna set it back to zero, so count.set0. Okay, so that works.

[00:03:15] But there's actually a subtle bug in this application. And the bug is that we're generating this unsubscribe function, which is the result of calling count.subscribe, but it never gets called anywhere. Now one way that we could fix that is to use the on destroy life cycle function. And inside on destroy, We'll call unsubscribe.

[00:03:42] In that way, we're not gonna have any memory leaks if there are lots of these components and they've been created and destroyed, all of our subscribers are gonna be torn down. But look at all this code. It's quite a lot for what we're trying to do. So Svelte has a trick up its sleeve.

[00:04:01] Because we have this fixed store contract. By which I mean the subscribe method. We can reference a store value by prefixing the store name with the dollar symbol. And we can just get rid of all of this code here, get rid of the on destroy. Get rid of the count value, get rid of the count.subscribe.

[00:04:23] Just take that store and prefix it with the dollar. And it works exactly the same way, under the hood, Svelte is creating that subscriber the same way that you would have done manually, except that it's always gonna clean it up when it's no longer valid. There are some caveats about how this syntax sugar works and they're detailed in this section here.

[00:04:53] So that was the writable store. There are some stores that you don't need to be able to set the value of or it doesn't make sense to set the value of them. You might have a store representing the mouse position or a store representing the user's geolocation. And those are read only, essentially.

[00:05:10] So this time in our stores.js tab, we're importing readable instead of writable. And we're creating a store called Time, has no initial value currently. And we haven't implemented the function that gets called when we first subscribe to the store, so let's do that now. First argument is the initial value, new date.

[00:05:35] I saw the time is 12:40:53, where I am. And when we first subscribe to this store, which is already happening because we're referencing it inside our app.svelte with dollar time. We can create an interval. It's gonna run once every second, And it's gonna set the current value to a new Date object.

[00:06:09] And then once everything is unsubscribed to this store, we can clean that up. So we're gonna return a function that calls clear interval, and then we pass in the interval. And so now we have this time store that is just gonna keep ticking up as long as anyone is interested in it.

[00:06:29] And that can be shared between as many components as you want. Finally, we have derived stores which are stores whose value is derived from other stores. Be they readable or writable or even other derived stores. So taking the previous example, we wanna have a store that represents the number of seconds that the page has been open.

[00:06:55] And we already have our time store setup. We just need to implement the App Store. And so, we're importing derived alongside readable. And the first argument to this function is a store. And the second argument is a callback that takes the current store value and turns it into something else.

[00:07:20] So we're gonna take math.round, And then we'll take the current time. Subtract that from the start time when this module was first evaluated. And then we'll divide it by 1000. And so now you can see that the store representing the number of seconds elapsed since the page is opened.

[00:07:46] Updates in sync with the store representing the current time. Now, you can derive a store from multiple input stores, and you can explicitly set a value instead of just returning it, like we're doing here. That's a little bit more involved. So if that's something that you need to do, then consult the API documentation.

[00:08:09] Which you can find up here, this link in the nav, next to the tutorial.