How Svelte Stores Make State Management Easy

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey friends what's up today we're going to learn how to manage and share reactive State across multiple components in SW but more importantly we're actually going to learn how JavaScript Works instead of being a JavaScript framework Andy right so that you have confidence regardless if you use stores or signals that you understand that they're almost the same thing otherwise you're always going to struggle trying to keep up with the latest changes but if you understand JavaScript you're more resilient to change you're going to develop a passion for your craft and have a deeper understanding for the things you're using all right so before I get started don't forget to like And subscribe and you can also support me by becoming a patron all right friends so here I have a simple counter example I want to be able to increment it decrement it and reset the value and here is how it looks in code so the problem here is that we have this counter example which I'm importing here from lib and I want to be able to increment it decrement it and reset it from any other component right and I want the value changing to be reflected here so how can we do something like this and the prob is that JavaScript by default isn't reactive right so even if I'm exporting this value I always like to challenge my belief so what would even happen if we try to reassign the value of an import right we can say counter 10 and then we get an error right it says cannot assign to counter because it is an import all right so now we learn that Imports in JavaScript are read only well that was a nice try but maybe as always we can turn this into some function then we can return some values and Etc but wouldn't it be great if anyone interested in counter updating can be notified about about this by subscribing to counter so how would that look like so here we have counter which can be anything right so now when this value updates it's going to notify this subscriber this subscriber and this subscriber and a subscriber can be anything from your component to a regular JavaScript module and then when we subscribe to this value we can use swel reactivity and each time this updates if we subscribe to it we can just reassign this value to the count inside of the swell component and thanks to reassignment in SW is going to update the UI all right cool so how does that look like well let's first create a function create counter we're going to pass it an initial value so first we want to keep track of subscribers and then we want a way to add a subscriber and then we want to notify the subscribers when it updates all right cool so how do we do this well first we need a way to keep track of the subscribers so we can say con subscribers we can make it an array but I prefer to use a set because we can only add unique values so we don't have to think about that and then how do we subscribe we just create a function subscribe and we can pass in a subscriber that's how simple that is and then we can say subscribers add subscriber that's it so how do we notify the subscribers well let's create a fun function update so each time we update the count value we're going to run the subscribers and notify everyone that subscribed so we can reassign the value of count by resolving the updator call back and we're going to pass the count so now we can say subscribers for each subscriber which is just a function right we can invoke the function and pass it the account value and I'm also going to disable typescript warnings because types are important here so we can focus on what's important all right so now we can create it we can say export con counter we can say create counter and pass it the initial value and this works thanks to closures and closures are something that you use all the time but you're not aware of it and people like to over complicate closures but the only two things you need to know about closures they only happen when you create a function and a closure in JavaScript just means that this inside function where you have to scribe and Etc has access to the outer scope and what is the outer scope well is the inside of this function right and not only this it's even the arguments because you mostly see something like this let current value equals count and boom this is a closure because these inner functions have access to the outer scope and we don't even need this because closures also work with arguments right because they have access to the outer scope and that's all it is to closures it's nothing complicated and we should also return this subscribe and update let's also create a set function because why not so we can say function set so we can set the value directly so when we reset the value or whatever else you want you can set set and it ass sets a new value so we can say count equals new value and now we can also run all these subscriptions and you're basically doing the same thing as in this update function right so we can use the set function so we can go like here so we can say set and then we can pass it updator with the account cool so let's save this and let's see how it works we can subscribe to counter let's go counter subscribe and now we can get the value we can log out the value and nothing happens if we go to this example here to the console so when we go here and even if I refresh nothing happens because it only runs the subscribers it notifies the subscribers when the value updates right so let's update the value somehow so we can say counter set to 10 now we can go here and you can see here we have 10 so each time the count updates all of the subscribers are going to get notified and to make this reactive in Sp we just need to create a count variable and now we need to reassign this value here so we can say count equals value let me just just remove the set here and we can just set it to count instead so now inside increment here we can say counter update we get the current count we can say count + one let's save this same for decrement say counter and for the reset function we can just reset it take counter set to zero all right so let me just refresh and let's see if everything works so now when we increment this value how beautiful is this so now this is reactive across multiple components so now increment here we just increment it here this doesn't really care where this count is located because we're importing this counter here which we created here so now when this gets incremented this subscriber here is going to run this call back which we pass the count value here this callback and now it's going to run and because in swell reactivity is achieved through assignment we say count equals value and now this is going to reactively update and let's see if reset works it does how beautiful is this friend you might have noticed something else if we go to our counter example we named create counter but there is nothing inside of here that's specific to a counter so we can make something more generic we can rename this to something like writable and then we can press contrl D let's select all of the instances of count and we can name its initial value but I'm just going to name this value and now we can rename create counter to writable and now we have something more generic we can reuse for anything and additionally we can return a cleanup function from subscribe so we can say return and we can say subscribers delete the subscriber and that's it so basically here is how you would use it you would just say const unsubscribe and if you have on Destroy method or wherever you're doing the cleanup you can just invoke unsubscribe let's just see as you can see we unsubscribed so nothing logs but if we comment it out anything should work the same as before how beautiful is this friends and we can also reset the value and that's basically it and what you just implemented is a swell store and it wasn't that complicated right and if you want to see the typed version you can find the link to the blog post in the description all right but what is the point of all this it looks like complicated if you see it for the first time and basically I tricked you into learning The Observer pattern I know the worst kind of villain that one that makes you learn so you can see here Observer pattern this is awesome site patterns def so use observables to notify subscribers in event occurs so you can see their implementation looks very similar except they're using a class but you can see they have subscribers here they keep track of it they have a separate unsubscribe method and they notify the subscribers and why this important well basically you just implemented a SW store how simple was that right it wasn't that complicated and this is important because the only way to be resilient to any change is to understand how JavaScript and the tools you're using work because even signals are observable and let me tell you signals aren't that different from a SW store the only major difference is that signals automatically subscribe for you when you use them so when you constantly think about these things and how these things work under the hood you're going to be more resilient to change if a framework is the only thing you know then you're not going to understand how things work right but if you ask questions you're going to develop a passion for your craft and a deeper understanding of how things work under the hood all right and now foreplay what is a swell store a swell store is just an object with a subscribe update and set method that allows you to manage and share reactive State across multiple components so instead of doing this yourself you just import right from SW so let's just delete all of this code and we can just import writable from SW store and now if I save this just go here so we don't unsubscribe right I'm just going to remove all of this code and everything should work the same as before so nothing changed right except we're now using the official swell store and now if you go to our example here always like to refresh for good measure and now we can increment the value and everything works like before so let's learn more about stores a store also accept a second optional argument which runs only after the first subscriber and returns a cleanup function when there are no subscribers anymore so let's see how this looks like so here I'm passing it a call back and we thinking why would I do something like this well we're going to look at another example later but for now if you have something that you want to initialize like a connection to some service you would do it here and then you can do a click clean up when there are no subscribers and that's really simple and elegant so we can say console log got a subscribers this only happens once when you get the first subscriber and now we have also a cleanup function so we can say conso log no more subscribers and this is only going to happen when your subscribers go from one to zero right and we should have one subscriber because we subscribed here under subscribe and now this runs only once so you can use this to initialize whatever you want and then for example if you go back to your component maybe you can do this inside on destroy or whatever if you need to do a cleanup but again let's just do the same thing as before unsubscribe and we can just invol unsubscribe and now let's see just say got a subscriber no more subscribers because we unsubscribed awesome so let me just remove this code and I'm going to save this and the other thing you can pass to this callback is a set and update function the same ones we implemented before right so we can set the initial value to 10 and even inside of here we can subscribe right so we can say count and then you can say console log count which we could have done here it would work the same right but I just want to show you that you can subscribe even inside the regular JavaScript module all right so now this should log once because we're subscribing to it and you can also Run update you can get the previous count and then you can do whatever you want if you need the previous value so you can multiply it by two and it should log 20 so let's save and you can see 20 if I refresh it again and you can see it also initialized the count to 20 so it works the same as before how beautiful is this friends and besides writable stores you also have readable stores so let me show you so we can also import readable so if you have a read only value and you don't want someone else to overwrite it on accident you can just create it here for example let's create let count readable zero and you can already see thanks to typescript that you don't get any other completion other than for subscribers you can only subscribe to a readable you can't actually change it because there's no set there's no update method on it and again let's just see let say count subscribe so this is a different store right so let's give it the value like 10 and now it logs 10 all right cool so let me show you when you need to derive some values you can use the derive store so let me just remove all of this it's not confusing so we have a derived store and a derived store is useful if you need to create a store based on the value from other stores so let's see how this looks like so here we have this counter but maybe we want want to create a doubled value so double count we can say doubled and we can use the derive store now we can pass it the store which is going to be counter and now we have a call back here we have access to the value inside and you can name this whatever you want and you might see something like this it says a dollar sign and they name it like this but this dollar sign actually has no special meaning it's actually really confusing they use this in the dogs because this syntax has actual other meaning which we going to learn about later and now we can just say count * two cool so now we can subscribe to the double value we can say subscribe and we can say count and we can conso log it out cool so now it's zero and we're going to get zero so now it's going to log again if we say counter set and let's set it to 10 so now because this is doubled it's going to run doubled and this is going to log 20 cool so now we get zero and 20 and you can also pass in multiple stores I'm just going to pass in the same store but this is how you do it you just pass it inside of an array so I can say counter counter and now you can get the values here you can say a if you want so we have to use an array AB so now you can get those values and now we can go here and use the values from both stores we can say a plus b cool and let's save this and now we get the same result as before and I also want to show you if you need to retrieve the value from a store and don't want to subscribe to it you you can use the get method so the get method is going to subscribe read the value and unsubscribe from the store for you let me just go here I'm going to remove all of this and let's give it initial value of 10 so we can say const count we can use get and we can pass in the store now let's log out the value of count it should be 10 so let's look at this even if you refresh it works as expected so if there's a situation where you need the value from the store but don't want to subscribe to it you can use get let me just remove all this code I'm going to set this back to zero and as you can see swell stores are awesome but they can get really tedious to use right so we've seen here not only do you have to subscribe to the value you also have to think about the cleanup and this really isn't that bad but imagine if you use multiple stores then this boiler plate would get out of hand quickly and thankfully swel is a compiler so you can write the code for us so we can take advantage of Auto subscriptions and we can use the dollar sign prefix to subscribe and unsubscribe to a store for us so let's see how this looks like and this is the best part because we get to delete code so check this out we don't need any of this junk count boom gun this subscription boom gone okay what do we do now well we just use the dollar sign prefix and SW is going to the Sugar this syntax so dollar sign counter and now this is going to work the same as before you go here when we update the value say plus can also decrement reset all right so now let's update our other component inside of increment here we don't have to do this so we can just remove and we can just say counter plus equals 1 so we can go to decrement instead of doing this we can say prefix counter we can say minus equals 1 so we decrement the value and in a reset function instead of doing set we can just say l sign cter equals zero and let's see if everything works how beautiful is this friends and we can reset the value and this dollar syntax only works inside of swell components because swell doesn't change how JavaScript behaves in regular JavaScript files so you can do something like this here and if you ever use stores in a JavaScript module then you have to use those other methods set to scribe update and Etc but if you're using a cell component this is how simp simple and beautiful using stores can be and you can also bind the value of a store so I can create an input and I can say bind value and you can pass it counter let's go here and you can see the value is going to be bound so stores are really beautiful and this is possible because he is a compiler and it dis sugars the dollar sign CX into the code you wrote before reducing the amount of boiler plate let me show you another awesome thing which are custom swell stores and basically custom swell stores allow you to encapsulate related logic within a store and expose a clear and specific API so instead of having all of this increment decrement and reset logic in these components we can put it inside of a single store and this is going to look familiar so let me just go here and we're going to create a function create counter and we're going to pass the initial value which is going to be count again familiar same as before but now we can D structure certain values from a writable right let's P it the count and now here we can get subscribe set and update so swell basically exposes to us these pieces so we can compose our own custom stores and to have a valid custom spell store the only thing you have to do is return the Subscribe method and that's it so now you can do any logic inside of here so let's go here and we can say function increment and remember because you're inside of a JavaScript module you can't use the sugar syntax you have to say update say count plus one so let just copy over this function we can name it decrement we can say minus and then we also have a reset function so we can say set to zero and this is how simple this is so you can do really anything and now we just need to return it so we return the subscribe so we can get the value right and then we return the other methods increment decrement and reset cool so now we just need to create this store and this is going to be shared across every instance in JavaScript module because we're going to export it from here so we going to say export con counter create counter and let's pass it the initial value and maybe you want this counter to be unique for every component in which case you can just create this inside of a component or wherever else right and that's how we're going to to get a unique counter each time all right so let's update our example here we don't have to do anything special inside of increment we no longer need this increment function we can just say counter increment can do the same for decrement so now it's all encapsulated inside this cool so now we can also go here let's remove reset counter reset and let's see if everything works so let's see we can increment and we can decrement and even reset it and that's it I can even go here and I can remove this bind here how beautiful is this friends all right friends so let's talk about using stores on the server so here you have this store we're going to subscribe to the count and then you're like okay maybe I want to update the count in the store from the server right is going to be reflected and actually this is really simple don't use stores on the server it's simple is that just don't and why is that well because stores are designed to manage State on the client and on the server each request is handled independently in the best case you're going to run into some weird issues and in the worst case you're going to leak data from users because you're muted in shared State on the server so in this example I'm just importing this counter so I reverted it back to this version so I'm saying update count so your user comes to this side let's just go to server here so your user comes to this side the count is zero and you're going to actually see something interesting whenever we refresh it's going to update but it's not going to even show here so you can only going to see a Flash and that is because your component gets rendered on the server and then on the client but once it gets hydrated back on the client is going to use the original store value so you're going to run into some weird issues and then let's for example you have someone else that visits your site and then you're going to also get another value for the store right so as you can see this is already a weird issue not to mention that you can have data that leaks like this and if we go to the component here we can see actually that it's not updated because we're just logging the counter from the store right but if you look on the server so I'm going to open it here and let's just open the developer tools here I close it here so let's just refresh everything so we can see data then page data but now as you see here it's going to log the value because we subscribed to it using count so you can see here is going to log the updated value on the server so let me just refresh a couple of times so increase the count to 10 as you can see it logs here and then another user can come in and they can get the version from the other person so imagine if this is some credentials or Etc it would be a complete disaster because the client and server state is separate and it's so easy to get into this sort of problem when the line between front end and the back end is blurred when using something like CIT but it's really simple just don't use stores on the server instead of that pass the data to the component so this can be pretend you can get the data from any other source fetching and Etc so just return it and then instead of relying on the store you can just P the data to any component that needs it or you can use page. data so as you can see here I refresh this so now it's going to be 10 again right and now we can just pass this data to the component that needs it and why is this awesome well let's say for example we have export L data so we have data count this is great for this component but maybe you have some other component like here and you're like okay now I need to pass this data here and imagine if you have a child of a child of a component now this would get really annoying well thankfully inside every component return from the load function you get the page data from the page store let me just show you how this looks like I'm going to use my snippet pre so this is the page store which you get on every request so you can see here it has data and this is going to return the data from the load function and you have access to this inside of every component so you don't have to paste data around like a hot potato if you need the data return from a load function inside of another component just use the page store from ckit let's look at another cool example which is using Sal stores with other libraries because a sales store is just an observable it has great interoperability with libraries that use observables like xate or rxjs and this is just a cool example I want to show you so let's go to the interrupt example and let me show you the code so inside of here I'm importing a readable from sales store from ma important create machine and interpret which really isn't important here is a simple toggle State machine I'm just going to collapse it because it's not important here is the cool part so we can create almost like a custom SW store use machine we can pass in the machine so here is how we initialize it we can just say service interpret and here's the cool part so we can say State equals we can create a readable SW store so we can pass it the state and now we can use the second argument to initialize something when we get the first subscriber and where do we get the first subscriber well here we're using this dollar syntax right so it's subscribing for the first time and then we can subscribe to the service itself from exit right so we can subscribe to it and then each time it updates we can set the state using set and now we can pass it the state and that's it that's how cool that is and we can also return a cleanup so the server stops when there are no subscribers and then we just return the state and send and this is how we can use it so we can say cons then we can do structure State and S from use machine just pass the machine and this is how it's going to work so we go to our for example and say off on off on of course this is a very simple example but I just want to show you how cool this is and of course you wouldn't have to implement something like this yourself because xate already has this for you and you can use xate SW so if you need that you can import use machine from I think it's xate well it's like this you can just import this and use it as is all friend let's talk about the future of SW I know I'm going to get at least one comment what is the point of learning stores right when there are runes which felt recently announced or signals and the point is that it's because you should learn JavaScript you should learn things regardless and how things work if you only know JavaScript Frameworks then you're going to see everything through a JavaScript framework so I'm going to go to the announcement here runs and of course I'm not going to explain runs in details here but I'm going to show you how this example looks like and how it's not important if you use a store or runs because they not only look similar but they also work similarly on under the hood so let's go to the bottom here and I'm going to go to the preview site just so I can show you the example to the preview site like this I'm just going to copy over this custom store that we created and I'm going to show you how similar they are let me just go here and awesome let me just see if I can indent this beautiful so remember how we had to know that weird rule about stores that we can't use the dollar sign syntax in JavaScript modules well this is gone with runes runes or signals are going to be the one universal reactivity in Sp you have to know this means that you have to know less things and they're also going to make you more productive I'm going to remove this because T script isn't supported here instead of writeable we use a signal so we can say let count you just have to type a couple of more letters no big deal and let's just say initial count and I'm going to reame this to initial count awesome so now you don't have to even know about this API look how cool this is and this works in your components and JavaScript files so you can say count plus equals 1 and we can say count minus equals 1 and even if we want we can say count e zero so now we can go here same as before we can say const counter create counter we can pass it the initial value and I'm just going to go here going to say H1 count is now if you say counter it's not going to work and you also need to return the values here let's go here I'm just going to return count increment decrement and reset and why doesn't this work well this is just JavaScript right because the value of count is going to be the same value as when we created this function so just knowing JavaScript this isn't spelt right we we can create a function out of this count and we can return count and this is why it's so important to know JavaScript and now we can say here counter do count and we invoke it because it's a function and you can see it works but there's another way how we can do it we can use Getters and Setters so the only thing you have to do here you can say get count or you can name this value whatever get banana right and this is just going to return the value of count and now you don't need to invoke this function anymore and this is really important to understand things like this because knowing JavaScript you don't really care about any of these changes because you know how it works this is just regular JavaScript and by the way you don't even have to do this thing this is just if you want to use this like a store right you want to make this reusable like all of this isn't required the only line that's required here if you want to use just this count in your component is just saying count and declaring it a stay that's it this is just if you want to make this reusable and import it from anywhere right this is when you have have to do this all right so now let's just update the example so I can say button so this is going to be on click so we can say counter increment same as before let me just copy this over and let me just make space just to see what's going on we can say minus and we can say reset cool so let's see decrement and we can save reset all right cool let's see if everything works and that's it boom how cool is this friends and again this is why it's so important to learn how JavaScript works now you no longer have to remember some weird rules of reactivity in SW because it just works as expected so the greatest tragedy of only JavaScript Frameworks instead of JavaScript is mistaking SW to rooms for other Frameworks instead of understanding that you can do anything so let me just really to show you how cool this is and this is what when people look like this they're like oh this is react andc because they only understand react they only understand Frameworks they don't understand JavaScript when you don't understand that you can be inspired and understand that you can do anything again this is the same example of course just because this API looks like react this doesn't work anything like react under the hood reacts reactivity works completely different but it's not important as you can see we can use the same API count set count because react didn't invent functions react didn't invent returning a tuple that you can D structure from it just looks like react but it doesn't it's not important right you can name this U State use whatever you can see it looks very similar again solid this is the same example but in solid it's use signal and this is actually closer to how solid does it because runes are signals so you can do this you like view you can create a wrapper W so you don't have to write all of this and maybe SW is going to expose something like this in the future so it's easier for you but you can see here we just use Getters and set letters this is just JavaScript and I hope this inspires you to ask questions how JavaScript Frameworks work and you realize it's not magic you're going to be more resilient to changes and gain a deeper understanding and passion for your craft all right friends and that's it if you like what you seen don't forget to like And subscribe and you can also support me by becoming a patron thank you for watching and catch you in the next one [Music] peace [Music] no
Info
Channel: Joy of Code
Views: 18,927
Rating: undefined out of 5
Keywords: sveltekit, svelte, stores
Id: L3uBfL-4dDM
Channel Id: undefined
Length: 32min 40sec (1960 seconds)
Published: Thu Oct 12 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.