Global Stores Are Dangerous

  Рет қаралды 18,038

Huntabyte

Huntabyte

Күн бұрын

Пікірлер
@Huntabyte
@Huntabyte Жыл бұрын
Forgot to go through the official SvelteKit Docs page on this topic, so I'll link it here. Highly recommend reading through this! kit.svelte.dev/docs/state-management
@Nintron
@Nintron Жыл бұрын
Time to nervously watch hoping I'm not making any of these mistakes.
@Huntabyte
@Huntabyte Жыл бұрын
😂
@SoloElROY
@SoloElROY 7 ай бұрын
Aaaaand I do
@phantasmalmira5430
@phantasmalmira5430 Жыл бұрын
One tip for using context API is to create unique key using Symbol() rather than strings so that there will never be any conflicting keys
@omomer3506
@omomer3506 Жыл бұрын
This should totally be a playlist of its own, Sveltekit No Nos
@coffeeintocode
@coffeeintocode Жыл бұрын
Another good video & thanks for calling out that this isn’t a SvelteKit specific issue. All meta frameworks will suffer from this
@zzonawav
@zzonawav Жыл бұрын
TypeScript Classes are crazy powerful used in this context.. I have been doing some things with JavaScript Canvas API with type instantiation and svelte components .. the performance and layering I am able to achieve with theses SSR components is blowing my mind.. it all works with reactive params! Really a game changer. I know a lot of people hate on typescript but the typescript class is my go to design pattern for many things in svelte.
@webstuffzak
@webstuffzak Жыл бұрын
Can't wait for the video about the power of classes with runes. Very very interested. Love your content!
@VeriousSmithIII
@VeriousSmithIII 5 ай бұрын
The class is a powerful tool. Looking forward to the class video.
@jimmielyon
@jimmielyon 6 ай бұрын
2:25 are you using excalidraw?
@CodeZakk
@CodeZakk Жыл бұрын
Hi thanks nowadays everybody is talking about nextjs and react you and joy of code the only channel talking about sevelte and sveltkit thank you. I started watching your channel and learning svelte for a while now thanks for your content!!🎉🎉🎉
@hanshurtig5943
@hanshurtig5943 10 ай бұрын
As far as I can tell, you could also use the page store to set state on the client side: // some js, ts or svelte file, but never .server.something import { page } from '$app/stores'; import { derived } from 'svelte/stores'' export const user = derived(page, $page => $page.data.user) Then import it wherever you want. Or am I missing something?
@AShaheen92
@AShaheen92 Жыл бұрын
Using Classes with state and setting it as a context is at another level! Can’t wait to start using svelte 5 after being stable. You really impress me with every video you upload. Wish you great time
@jaycool-lb9kj
@jaycool-lb9kj Жыл бұрын
For sure! Cant wait to experiment with this
@Huntabyte
@Huntabyte Жыл бұрын
Thanks a ton! I love the classes a little bit _too_ much, excited to share more about them!
@aytee5862
@aytee5862 5 ай бұрын
I implemented this just as you show, but I get the error: "Cannot use 'X' as a store. 'X' needs to be an object with a subscribe method on it." when trying to use the get-function you've defined when trying to access the value with $ prefix
@xWe2s
@xWe2s 11 ай бұрын
Can you make a video about sveltekit v2 + svelte v5 including Runes? Are there something specifics in setting such thing up?
@acharafranklyn5167
@acharafranklyn5167 Жыл бұрын
Thanks for making these videos again.... you took a lot of break
@Huntabyte
@Huntabyte Жыл бұрын
You're welcome! A break from videos but not a break from Svelte/code 😉 I've learned a ton during that break that I'm looking forward to sharing!
@AZombieHippie
@AZombieHippie Жыл бұрын
Do you find that classes in Svelte 5 have some unique offering beyond returning an object from a function closure with getters? I've been really happy so far with closures for encapsulating business logic nicely
@jesper.ordrup
@jesper.ordrup Жыл бұрын
Really great to bring this up again. While its not s svelte issue per day it sure becomes a svelte related problem when svelte adds functionality that relies on this. I wish that svelte stores directly solved this, also compile time warnings rather than workarounds. It makes svelte less "simple"
@Huntabyte
@Huntabyte Жыл бұрын
The problem is really only introduced with SSR, so if you're using Svelte as an SPA with 0 server side rendering, then that global variable would be global only to the client, in that case its fine. The same would be true in Nuxt or Next if you imported a global object, which is ultimately what these are!
@jesper.ordrup
@jesper.ordrup Жыл бұрын
Agree 🎉
@seunghwanjeong5348
@seunghwanjeong5348 Жыл бұрын
Hi! Thank you for making amazing video every time :) I think misunderstood the concept of runes. I would try what you recommend👍🏻
@Huntabyte
@Huntabyte Жыл бұрын
You're very welcome!
@stoched
@stoched Жыл бұрын
I understand everything you're saying in the video, but something you didn't explain is why is it that using setContext/getContext fixes this global state issue? Because in my mind when you set the context key to some constant then it would be the same reference for everyone on the server? So what makes setContext uniquely preserve the state per user and prevent it from leaking between each other?
@Huntabyte
@Huntabyte Жыл бұрын
I apologize for not clarifying further! It's not that `setContext` uniquely preserves the state per user, its that the state isn't able to be referenced globally, since it's initialized inside of (2) closures in this example - the `` tags, as well as the `setUserState()` function. You can't reference something _within_ those functions from outside of them, unlike a global object or global writable being exported from some module.
@stoched
@stoched Жыл бұрын
@@Huntabyte Hm I think I'm following. Are you saying if you have UserA and UserB: If UserA has already been on the site for awhile then the root +layout has already ran (which sets the context). That won't re-run at all. But if UserB visits the site then that will trigger +layout to render on the server side which re-initializes everything inside that context? Since it's a new instance of the context happening each time +layout is rendered on the server it will always be unique for each visitor ( and properties won't bleed into other users state, etc). Is that correct?
@Huntabyte
@Huntabyte Жыл бұрын
Yes but the context in and of itself isn't what's helping here, it's the fact that we have the creation of that store being done inside of a function, and the state itself isn't being exported from a global module. A good rule of thumb is to never put the keyword `export` in front of some state that you wouldn't want potentially persisted between requests.
@stoched
@stoched Жыл бұрын
@@Huntabyte Makes sense! Thanks for taking the time to explain I appreciate it!
@gunarcom
@gunarcom Жыл бұрын
Thoughts on the solutions using weakmaps on the server to prevent leakage?
@Huntabyte
@Huntabyte Жыл бұрын
I haven't dug into those enough to form thoughts, I just went with the recommended approach from the SvelteKit docs!
@gunarcom
@gunarcom Жыл бұрын
@@Huntabyte that's fair, I've been following that github discussion thread for months.. I am using one of the "ssr safe" packages on a personal site and it seems to work well, it uses weakmaps under the hood, which is similar to the way context stores work from what I gather. Looking forward to runes and hopefully addressing this pain point that I think most everyone runs into and great vid btw :D
@laztheripper
@laztheripper Жыл бұрын
What I do is still use global state, but I never update the SSR values of these stores after initialization with sensible defaults. This means all my pages can be SSR rendered, with for example no current session active. This works better than expected because client states should never change on the server anyway, and I've wrapped the server side versions with a function that throws an error if the server side state ever changes. I have a big problem with the context api. All of the code you've shown can only be ran at the root of a .svelte component file. Meaning, it's impossible for regular JS classes and libs to import the global state. You might think sure, but then you can update a store with the current context, but you've just reproduced the same issue from before. I keep running into this issue, that I really need something like the $page store that is per request, but accessible from anywhere and/or editable by my own code.
@Huntabyte
@Huntabyte Жыл бұрын
You'd have to be calling those functions somehow within your components though right? In that case you can pass the store into those functions and handle it that way! Of course its a matter of preference and it's nice that you have the exception being thrown to avoid any issues!
@laztheripper
@laztheripper Жыл бұрын
In simple cases, yes you'd use the store directly. But in more complicated sites, the state is probably consumed by multiple other classes, and then those might be visually represented in a component. So those 2nd order classes need a way to access state that doesn't depend on a component fetching context.@@Huntabyte Note that I've pushed svelte(kit) maybe a bit past what it was designed to do. I built an ecommerce site with websockets, CF public caching, internal request chaining so that even the site itself gets data from its own apis, rolled my own auth with email/pass (with email confirmation), google / discord oauth, SEO, dynamic sitemaps and xml feeds, and a lot more. So I've ran into most of the sharp edges by now, and one of them is global state.
@cory2300
@cory2300 Жыл бұрын
omg why is this not blasted on the SK docs. Thank you for this video honestly - you saved my future ass.
@Huntabyte
@Huntabyte Жыл бұрын
There is a whole page dedicated to it, but perhaps it should be more obvious! kit.svelte.dev/docs/state-management
@supbra1
@supbra1 Жыл бұрын
Not sure if I understand - what is the unsafe way? Did you show it in the video?
@Huntabyte
@Huntabyte Жыл бұрын
At the beginning. Exporting a global `writable` store and importing to various modules/components!
@d4yno
@d4yno Жыл бұрын
Whats the benefit of using classes?
@windar2390
@windar2390 Жыл бұрын
classes can bundle a bunch of methods and stores. of course the same is possible with object factories. but classes are "cleaner" and work better with vsc-intellisense. (i worked first with object factories, but got annoyed with not working intellisense. since i work with classes, i dont have these problems anymore.)
@tuvshinbayartuvshinzul8489
@tuvshinbayartuvshinzul8489 Жыл бұрын
TLDW; always use it with Context API if you need a global state.
@Huntabyte
@Huntabyte Жыл бұрын
Wouldn’t this technically be TLDW?
@tuvshinbayartuvshinzul8489
@tuvshinbayartuvshinzul8489 Жыл бұрын
yes 😅
@tuvshinbayartuvshinzul8489
@tuvshinbayartuvshinzul8489 Жыл бұрын
edited
@omomer3506
@omomer3506 Жыл бұрын
Okay can someone explain the {children} =$props i haven't seen it in sveltekit
@laztheripper
@laztheripper Жыл бұрын
It's just how you get variables you passed to a component in svelte 5. It's really just destructuring.
@windar2390
@windar2390 Жыл бұрын
this has nothing to do with svelte. this is javascript object destructuring.
@omomer3506
@omomer3506 Жыл бұрын
​@@laztheripper Am not talking about the destructing itself, but what is the $props() function i havent seent it
@omomer3506
@omomer3506 Жыл бұрын
​@@windar2390not talking about the destruction but $props() most $ variables are native to svelte since it compiles them, , and i haven't seen this function before
@laztheripper
@laztheripper Жыл бұрын
As I said it's how svelte 5 passes your component variables. If you aren't on svelte 5 then it's normal you haven't seen it. within MyBanner, you'd get the title from $props() instead of export let title;@@omomer3506
@benfrese3573
@benfrese3573 Жыл бұрын
lol that thumbnail (espeically like the little huntabyte logo)
@Huntabyte
@Huntabyte Жыл бұрын
I'm glad you appreciate it 😂
@derpenz5376
@derpenz5376 Жыл бұрын
Do we even need Stores in svelte 5?
@Huntabyte
@Huntabyte Жыл бұрын
Yes, but rarely.
@windar2390
@windar2390 Жыл бұрын
Thats exactly how I do it. :) But I dont put stores into context, but a main-class that contains all my stores and handlers. export let data: LayoutData; const main = new Main(data); setMainToContext(main); in other components: const main = getMainFromContext();
@laztheripper
@laztheripper Жыл бұрын
Meaning you have to getContext() anytime you need this data. Which can only be done at the root of a component. How do you import your global state into other .js files (not components)? Because I haven't found a clean solution for that. Svelte really needs a per request store/api like the $page store, but that is accessible outside components and editable by our own code.
@windar2390
@windar2390 Жыл бұрын
​@@laztheripper i dont know what exactly you mean with global state. all my user-data is saved in the main-stores. all my static data (for every user the same) is saved in normal js/ts-files. if you need access to user-data there are only 2 ways. 1) you get the data in the component and pass it down to your functions 2) you put your functions in the main-class as well. (my choice) when i have to mutate userdata, my code looks like this: const main = getMainFromContext(); const lists = main.lists; lists.addNewList({listName: 'Oh, hi Mark!'}) const paraController = main.paraController; paraController.setDarkMode(1) the nice part is, as soon as "main" is loaded, you are "free". every function has access to every data. but there are some tricky situations in hooks.server.ts, where main never will be loaded.
@Huntabyte
@Huntabyte Жыл бұрын
You can pass the stores as an argument to whatever function your calling and it will work the same as importing :)@@laztheripper
@Huntabyte
@Huntabyte Жыл бұрын
This is a brilliant way of handling this!
@laztheripper
@laztheripper Жыл бұрын
Which means again the source of the call has to be a component that gets the context. If for example I have websocket messaging class (real case btw), and I want to use global state in that class when a message is received, I need to have a component somewhere to get the context and hoist it into my class instance so that I can use it later, and then I have to get() on the store to access the data, which does a subscribe() and unsub() after which is not good. I've coded solutions for this ofc, but they aren't simple and I shouldn't have to. Alls I'm saying. Forcing everything through components, when a lot of code is purely transactional makes no sense, a lot of it doesn't have a visual representation, and I shouldn't be forced to create dummy components to make my state work.@@Huntabyte
@SilvestreVivo
@SilvestreVivo Жыл бұрын
I think this doesn't prevent the main problem: layout.server is loaded each time you navigate in SSR. Besides that, you have the $page.data object to collect everything from layout.server and have it available among all components in SSR.
@Huntabyte
@Huntabyte Жыл бұрын
The store is created inside of a closure so it does in fact prevent the main problem. Additionally, $page.data also uses the Context API under the hood, see: kit.svelte.dev/docs/state-management#using-stores-with-context
@Hugos68
@Hugos68 Жыл бұрын
How is the server side layout rerunning relevant to the context API, the context API is only client side, so it can never leak to the server
@SilvestreVivo
@SilvestreVivo Жыл бұрын
@@Huntabyte it doesn't matter if it is inside of a closure. The layout.server.ts file will run each time you navigate, so it will fetch from the API the data not only once. For the second thing, if $page.data solves the problem, why do we need to create again the same? My comment is about an app I am building now and I am struggling with this too.
@SilvestreVivo
@SilvestreVivo Жыл бұрын
@@Hugos68I didn't say anything about that. I am talking about something totally different.
@nicky-hajal
@nicky-hajal 11 ай бұрын
@@Hugos68 Just to clarify: if the site is running SSR, the context API does run on the server and is the crucial element that prevents data from leaking between requests.
@seanknowles9985
@seanknowles9985 Жыл бұрын
Also how are you using $props when svelte 5 hasn't been released yet?
@Huntabyte
@Huntabyte 11 ай бұрын
I'm using the prerelease version to start getting experience with it and trying to find any bugs along the way to raise to the team!
@nomadshiba
@nomadshiba Жыл бұрын
i always stick with PageData and ActionData. dont need to invalidate anything manually because i just use form actions with `use:enhance`.
@Huntabyte
@Huntabyte Жыл бұрын
This is perfectly fine for a lot of use cases! When you want to start adding custom store logic/have really really reactive apps, you'll likely reach for your own stores!
@Huntabyte
@Huntabyte Жыл бұрын
Also, the `$page` store actually uses the Context API under the hood!
@ntnon
@ntnon 11 ай бұрын
good good content
@ScriKidding-eg6vn
@ScriKidding-eg6vn Жыл бұрын
damn this guy is brilliant
@brookesstephens
@brookesstephens Жыл бұрын
Definitely made that mistake!
@Huntabyte
@Huntabyte Жыл бұрын
As have I!
@meaningmean
@meaningmean Жыл бұрын
Thanks
@Huntabyte
@Huntabyte Жыл бұрын
You're welcome!
@st3ddyman
@st3ddyman 5 ай бұрын
Svelte started so clean and simple but with runes and state is getting so much more complicated. What is wrong with just defining a store in a stores.js file and importing and accessing the value everywhere. Export Let is so much simpler than $props too. It is starting to feel like oldskool REACT developers have taken over the codebase.
@Huntabyte
@Huntabyte 5 ай бұрын
If you're building an SPA with no SSR, you can still define / export those global objects. If you're doing any SSR though, you just need to be careful about what state you're exporting globally to ensure you aren't leaking data between requests.
@st3ddyman
@st3ddyman 5 ай бұрын
@@Huntabyte I always back my state on the client side via localstore. I don’t see the scenario where the data can flow back to the server. In my experience the server renders the page using the default values provided for stores , passes it to the client then the client rehydrates it using the actual value of the stores. Unless you were to post the value of these stores and write them in the server side load functions, the data direction is only ever one direction.
@seanknowles9985
@seanknowles9985 Жыл бұрын
why are you mixing functional and class patterns?
@tobias3581
@tobias3581 Жыл бұрын
Thanks for sharing. Kit is opinionated and nice in theory but, low quality types, weak route validation, and offering a backend (kit) to a reactive systems (svelte) with such footguns. Kit is so opinionated in code organization while simultaneously not taking responsibility for its intended effect. Kit is like bathing in a pool of pee and being told to stay in the corner
@zzonawav
@zzonawav Жыл бұрын
curious to know what your go to JavaScript front end is.
@tobias3581
@tobias3581 11 ай бұрын
@@zzonawav they all suck 😂 on paper, the new direction of solidstart is on point, but historically little popularity and weak typing are concerns. Remix is pretty nice in react land. I still think Vue is the best across the board in terms of DX, typings, productivity, ecosystem, tooling. Nuxt is a bit magic but lots of nice things, so I’d go with Nuxt. If you have loads of time and want the best then solidstart or leptos in rust -
@smen66
@smen66 9 ай бұрын
Has the state file to be called state.svelte.ts or could it be also state.ts? Is there a difference?
@soberstudy160
@soberstudy160 5 күн бұрын
If you are using reactivity yes it has to be called *.svelte.ts, if not name it what you want
Don't Sleep on Svelte 5
12:22
Huntabyte
Рет қаралды 45 М.
Master The Svelte Context API
18:07
Joy of Code
Рет қаралды 8 М.
Don’t Choose The Wrong Box 😱
00:41
Topper Guild
Рет қаралды 62 МЛН
Правильный подход к детям
00:18
Beatrise
Рет қаралды 11 МЛН
REAL or FAKE? #beatbox #tiktok
01:03
BeatboxJCOP
Рет қаралды 18 МЛН
“Don’t stop the chances.”
00:44
ISSEI / いっせい
Рет қаралды 62 МЛН
Svelte 5's Secret Weapon: Classes + Context
18:14
Huntabyte
Рет қаралды 30 М.
Svelte 5 Ruined Svelte (and that's why I love it)
12:37
Ben Davis
Рет қаралды 13 М.
Practical Svelte 5 - Shopping Cart
25:10
Huntabyte
Рет қаралды 21 М.
Using React Libraries Inside Svelte
16:55
Joy of Code
Рет қаралды 6 М.
Avoid Leaking User Data In Your SvelteKit App
24:31
Joy of Code
Рет қаралды 5 М.
Svelte 5 Is Like React, But Better
19:33
Theo - t3․gg
Рет қаралды 81 М.
Use Svelte 5 Snippets To Reuse Markup Without Creating Components
17:41
Why Your Load Functions are Slow
8:24
Huntabyte
Рет қаралды 21 М.
Svelte 5 runes: what's the deal with getters and setters?
11:22
Rich Harris
Рет қаралды 45 М.
Don’t Choose The Wrong Box 😱
00:41
Topper Guild
Рет қаралды 62 МЛН