850: Manage State in JavaScript Like a Pro!
en
November 20, 2024
TLDR: Scott and Wes discuss state management concepts like reactive state, store, immutable vs mutable state, state updaters, signals, global vs local state, libraries, and approaches to manage state in JavaScript, including Reducer-based, Mutation-based, Atom-based and more.
In the latest episode of the Syntax podcast, hosts Scott and Wes delve into the intricate world of state management in JavaScript. This discussion is vital for developers who wish to build efficient web applications, as understanding state is crucial in handling data that reflects the current condition of an application.
Understanding State
State, in the context of JavaScript applications, represents the data that indicates the application's current status. It influences both behavior and appearance. Here are key terms discussed in the episode:
Common State Jargon
- Reactive State: Automatically updates the UI when the underlying data changes.
- Store: This is a place where state resides, often consisting of methods for interacting with that state.
- Immutable vs Mutable State: Immutable state cannot be changed directly but requires functions to create new instances of the state.
- State Updaters: Functions responsible for modifying the state, can be simple or complex (like reducers).
- Signals and Observables: Patterns for managing state changes and notifying parts of the application when state updates occur.
Key Concepts
- UI as a Function of State: Emphasizes that the UI should reflect the current state of the application.
- State Machines: A structured approach to handling state transitions and ensuring predictable state management.
- Global vs Local State: Differentiates between state accessible across the entire application versus state confined to specific components.
- Computed State: Refers to derived data that is recalculated based on changes to other state values.
Approaches to State Management
Scott and Wes categorize state management strategies into three main approaches:
- Reducer-Based State: Utilizes a store and actions to manage changes. Libraries like Redux exemplify this approach, involving more boilerplate yet offering reliable state management.
- Mutation-Based State: Provides a simpler way to manage state directly, similar to using plain JavaScript objects. Libraries like Svelte leverage this approach.
- Atom-Based State: Agencies each piece of state as an atomic unit, promoting more granular data updates. Jotai and Recoil are relevant libraries that use this pattern.
Ways to Hold State
State can be held in various methods:
- JavaScript Objects: Basic form of storing state directly.
- URL Parameters: Effective for managing application state across navigation, enabling shareable links.
- Local Storage and IndexedDB: Useful for persisting application state across sessions.
- FormData API: Manages complex data types from forms, which is particularly useful in modern web applications.
Global State vs Component State
- Global State: Data shared across various components in the application, ideal for user settings and preferences.
- Component State: Local to specific components used primarily for UI state management (e.g., form inputs).
Sharing State Between Components
The podcast discusses two primary methods:
- Import/Export: Centralizes state management into a single file that can be imported where needed.
- Context API: Allows state to be provided at a higher component level and consumed by nested components, though may lead to performance issues if not managed properly.
State Management Libraries
Scott and Wes also discuss a variety of popular state management libraries:
- Zustand: Known for its simplicity and efficiency, allowing direct state manipulation in a React environment.
- MobX: Focuses on observables, offering a reactive programming style but often considered complex.
- XState: A library suitable for applications requiring state machines, facilitating controlled and predictable state transitions.
- Easy Peasy and Jotai: Each offers different abstractions for handling state more effortlessly.
Conclusion
The discussion encapsulates vital insights for developers looking to better manage state in their JavaScript applications, highlighting how different strategies and libraries can cater to unique application needs. Mastering state management is essential for enhancing performance and user experience in modern web development.
Key Takeaways
- Understanding different state management approaches can lead to better application design.
- React and other frameworks benefit from specific libraries tailored for efficient state management.
- Centralized state management, whether global or local, is critical in complex applications.
By incorporating these concepts and tools discussed in the podcast, developers can elevate their JavaScript skills and build more responsive and user-friendly applications.
Was this summary helpful?
Welcome to syntax today. We got a show for you on state management and JavaScript. This is kind of an interesting one because we all have to manage state in our application. And there are many different libraries out there. There's many different approaches. You're hearing all these words like signals, reducers, actions, immutable reactivity, state machine, global, local. If you're using react, you're using a different framework. You're using vanilla JavaScript. There's all kinds of things to sort of consider.
we're going to do a show today that will sort of break down the different state management approaches, different ways to hold state, things that you should consider as well as go through some of the more popular options in the state management world right now. My name is West Boss. I am a developer from Canada with me as always. Scott, how are you doing, Scott? I'm doing good, man. Just chilling. Actually, literally chilling. It's cold here in Colorado. So yeah. Oh, man, we have
Oh yeah, we had to open the windows last night. It's like summer weather still here, which is wild. Oh yeah. Considering it was snowing this time last year. We have the classic.
Super cold at night, super hot during the day flow going on right now. I'm into that. Open the windows, let me freeze. Then open the windows, let me cook during the day. That's right. Real quick, let's talk about something at Sentry is Behind. It's the open source pledge.com, so they just rolled this out.
Having encouraging other companies to pledge part of their Profits part of the revenue to open source so the open source pledge comm is really cool initiative You can go to it and see there are tons of companies on here that are paying actual maintainers So you could take a look at the list century 135 devs they are contributing three thousand seven hundred and four dollars per developer back towards open source and there's a huge list of
companies that have sort of taken the pledge. I mean, like, you know what? We use open source to run our business. It's probably time that we give some of that money back to open source. Make sure that we have a healthy community. So check it out. And if you have a boss or you are a boss, I encourage you to sign up for it as well. Open source pledge dot com. Yeah. Hey, let's let's actually even shout out. Maybe we should shout out some of these companies that are taking this pledge. One of which that I've been following for a while is eMERGE tools. I do follow eMERGE tools on Twitter.
No. They're good follow. They break down.
apps. And they show what libraries apps are using. And these are all iOS apps and production apps. And so they'll just open up the FedEx app and talk about what percentage of the app is localization and fonts and whatever. And it's always fascinating whenever one of these comes up. They have a kind of like a daisy disk graph for dependencies for apps and talk about where the size is going. So a shout out to Emerge
uh, tools on Twitter specifically, I think, is where I follow them or get the most information from them, but cool of them, see them on the, uh, the open source pledge.
All right, let's talk about state. So what is state? State is a representation. It's data that represents the current condition of your application, right? The current state of your application. And it determines things like the behavior, how your application acts, as well as the appearance. What does it actually look like? So I thought we're first going to start off with some common words that you're going to hear us talk about. So just go through some of the buzzwords. Then we'll talk about the sort of the three big approaches to state management.
Waste a whole state global versus component state, and then we'll go into state libraries that you could possibly be using. So first one we have here is a reactive state. This is a word that you're going to hear quite a bit. And what that essentially means is that when you're building an application, you take your state, your data, and you put it into your templates, a reactive state will update
those templates when that state updates, right? The very simple example, you have a counter, you increment that value by one, wherever that variable is that used in your templates will update itself. Yes. Next one is store. And a store is just a word that people often use for a place where you put your state. I mean, people sometimes just call it a state. Sometimes people call it a store, a data store. Basically, a store is someplace that your data lives.
Yes. And a store, often we're going to talk about the different types of it, but a store will also often include the logic as to how that store can be interacted with, right? So it'll include a set of functions for updating, deleting, modifying the data in the store.
We also have immutable versus mutable. What this means is that can you directly reach into your state and update it directly? Or is it updated via a set of updater functions? So immutability is the idea that you should not just simply, let's say you have an object called Wes and it has an age of, I forget how old I am, 37, 36, something like that.
and you want to increase the age, you don't, for in a mutable state, you would simply just say, West that age plus plus or West that age equals 100. A mutable state would have a function that takes in West and returns a new instance of West so that you're not actually going into the value and updating it.
Yeah. Well, it'd be like if we were cloning Wes, like, if we put Wes into a cloner and transported him somewhere else, disassemble all his atoms and create a new version of him with changes. Next one is state updaters. These are functions that update state. Now, this can be done very simply with just a simple, like,
.setState or setState and this can be done with a .set but this can also be done in a much more complex way of something like reducers where you're taking in the old values or taking in the new values and you're manually merging them yourself.
A signal is we're not going to go too deep into signals on this because we can do a whole show on it. We have and we probably should do another one, but a signal is a way to manage state that has both a getter, which is how you consume the state and a setter that you use to update it. And then there's this idea that if you want to listen for when that state has changed, it's called an effect.
So that's another thing you're going to hear is basically just like watching for changes on that state is often called an effect. Yes. Next one is observables, which with observables, you know, and the observer pattern in general is just you can think of you're observing something, you're listening for something, you're waiting for something to change. So with observables, you're being able to listen for changes on them and respond accordingly.
Another kind of saying that you're going to hear is UI is a function of state. And what that means is that in order to get the UI for your application, it has to take in the data, meaning that you can derive any UI of your application based on its actual state. And as you get into more and more complex applications, for example, TL Draw is one of my favorite applications. This is like a little
Not a little, it's a drawing application, like a whiteboard, right? And there's real time in there and you can select on something you've drawn and you can right click. And the thing that always gets me is that when you right click on one of the pieces in the application, there's a whole context menu. And the parts of that context menu depend on
what you have selected, maybe what color it is, if you've selected multiple things. And I often think about how complex that simple right click is on TL draw because there are so many decisions that need to happen before they can simply display the actual options that are there. And I always think about that as being a very good example of the UI of the right click
takes in the entire world of what you've clicked and maybe even stuff behind it and it gives you a set of options to arrange them and copy paste them, move them around, select them, delete them, et cetera. All right, next one is a state machine. And now a state machine is an interesting way of working with state where
any individual state has basically several options that it can do, but only do from that state. So if you think about like, you have a piece of state, perhaps that state is a string. A lot of times when we're working state with state, we'll just call a set state and update that string to anything. But when you're working in a state machine, it doesn't quite work like that. You have a state machine, you have a piece of state, there's only a
a defined path of places it can go from that. So basically, you have your state and then you tell it which path to go next. And then now it's in that state. And it can only then go from other places of state. This kind of is at odds with when people use things like Boolean variables for things like
is open or something like that. You're more or less like, all right, the status of this thing is now it is open. And therefore, that brings along a lot of other properties. And from open, where can this go? Well, it can only go to closed from open, you know, from open to closed. And then from there, you can build off this whole tree of a state machine.
Yeah, it's a lot more complex. However, if you've ever been in an application where you think, hmm, I shouldn't be able to do that when this thing happens. Totally. Or like if you have like a thousand booleans or like, all right, I'm going to display the right click. And then you have a thousand if statements. So well, if there's this is set, but they also have selected this or if you are currently in this mode, but you're allowed to do this.
Holy hell, that can get very, very complicated very quickly. So I've not had to use a state machine in applications that I have built, but I have talked to lots of people that build much more complex applications, lots of desktop software. We had Andrew on who works at Descript and he says that is very complex happen. That's a massive state machine.
Yeah, I tend to work with all of my state that is complex as even most of my state, I'm going to say in general, as a state machine light where I'm not, I'm like refusing to use Boolean values for state in that sort of way. And I am more or less.
not adhering to something as strict as some of these libraries, like x-state, but still utilizing some of the principles. The ideas behind it. Binding state, this is an idea of being able to update state when you are changing it. For example, if you have a piece of state, which is what's your name? And then you also have that state
in an input. If you change that input, then that state is often needs to be bound to back to the state so that when you change the input, that state is also updated. I feel like I'm saying state a lot.
Yeah, I feel like that's an unfortunate thing that's going to happen in this episode, because it's really hard to even like discuss state without saying the word state. Another one is global versus local states. You could think of this as global as state that your entire application needs to access, where local is state that only one specific, even like chunk or component needs to access.
uh, computed, derived, or selector state, this is the idea that your state is actual data. However, if you want to display that data in a different way, or if you want to generate state based off of that,
For example, if you have a price for an item in your state, or your cart might be 5001, but when you actually want to display that value, you might use a derived state, which will then go ahead and format it.
It also could be state that needs to be multiplied by two and then you need to listen for when that state is higher than a certain value. So it's not simply just how to format it, but it could be a piece of state that depends on some other state and needs to be recalculated every single time that it is updated.
All right, so let's talk about the kind of three ways to attack state. You have reducer-based state, you have mutation-based state, and you have atom-based state. So reducer-based state, and these are all
handy in different aspects of your application and sort of how you like to approach it. So a reducer based state is like Redux. Redux is probably the most popular reducer based state. However, there is several of them out there. And then the way that a reducer based state works is that you have a store, which is
It has your data inside of it. And then you have something that are called actions. And actions are ways that you can update your state. They describe what will happen along with any argument. So for example, you might want to increment a number by one. You might have an array of comments, and you want to add additional comment to that. You might want to delete an item from a list of posts. So an action would be something like increment, add comment, or remove thing.
whereas you have a reducer. The reducer is the actual function. That's the actual business logic as to how do I increment it? How do I add a comment? How do I remove an item from that array? The reducer takes in your current state, does the work, and then out the other end returns you back the modified or updated state. So the whole idea there is that your state is immutable, meaning that you take your old state,
and then you return a new state from that. And the benefit to that immutability is you can have some really cool dev tools where you can sort of scrub back and say, oh, what happens if I don't do this specific action? You can see what actions have been taken and you can sort of time step through that, which can be really handy in complex applications.
Yeah, totally. There's also the word dispatch where with a dispatch, it's basically how you trigger or fire that action. So we mentioned that the actions are the thing that you're doing. The reducer is the work itself. And dispatching is the firing of that action.
There's also subscribe where you're listing for the changes and you can use it to update the UI. I found this flow. When I did not understand or use Redux, I found this flow to be daunting from a viewpoint. Like looking at it, you'd say, man, that's a whole lot to update a variable. And I feel like a lot of people felt that way too. However, once I actually used Redux,
I gained a little bit of a fondness for it, which maybe it's Stockholm syndrome with React in general, where at first you're like, oh, this is all too complex. And then later you're like, well, it's kind of nice. I can kind of see. Yeah. And eventually I kind of have taken a step back into the more simplistic view of things.
But I still do understand the value of a flow like this for keeping things organized. I think the most important thing with something like this is that it is a highly organized system, and I think that can help a lot of developers maintain their applications.
Yeah, it's there's a lot of boiler plate. Like if you simply want to have a variable of is cart open. Yeah. Yeah. What you're doing is you're creating a store that has an action of open cart, closed cart, toggle cart. You'll have a reducer that that will update that variable. Then you'll have a dispatcher, which fires off the open cart action.
And then you could also subscribe to it at a different part of your application because if the card is open, then maybe you want to do something else in your navigation where the navigation is a bit smaller. It's not for simple stuff like that. It's for when your application is extremely complex.
and having a very rigid system in place allows for those things not to sort of get out of hand. Because otherwise, if it's super simple, which is our next one, which is mutation-based state, which is probably the simplest option out there, which is you simply create some sort of store. And like Svelte has a really good implementation of this. There's kind of lots of them out there. At the very simplest, you could just make a variable.
that has a number in it, or you could have an object with a couple of properties on it. And when you want to update that state, you simply do it like it was JavaScript. You say west dot age equals 57, or you can delete a property or push an item into an array, right? Or filter that array and then overwrite the thing. That's mutation based. And the way that that works is generally it either uses a getter, getters and setters on an object,
or on a class that you can use them on both. So in JavaScript, when you set a property and when you, like you can say West dot age equals 50, or when you get a property, which is console dot log West dot age, those are getters and setters. And
By default, they're the same thing, but you can overwrite the logic with your own functions as to how does that value actually. And usually what happens is the actual value itself is internal on that class. It's either a private value on a class or it's like an underscore age value that lives inside of an object. And then you also have proxies as well, which is a proxy is
Sort of a function that sits in front of accessing an object. And you can sort of intercept when somebody runs a getter or a setter on that object. And you can determine what actually happens. Yeah. You could think of a proxy as kind of like a stand-in for the actual object. But it's been modified to have extra functionality added onto it. So it's like kind of, like you said, it's intercepting. It has potentially additional functionality. And it represents the object itself.
Proxies are kind of annoying when you have to work with them sometimes. Oh, yeah. For instance, the new state is all proxy-based. And sometimes you want to spread out some state. And with dealing with the proxy, you actually have to take a clone of that or a snapshot of it before you can actually access the real object behind the scenes. Oh, yeah. Yeah. So I'm actually curious about this. You just upgraded the syntax website to Svelte 5. Yes. In Svelte 4, a lot of the
state was just mutation base, meaning that you just create a variable and you can put the variable somewhere, you can overwrite that variable with a new value and it's all reactive and it just works. You don't have to know what a getter or setter or proxy is in most cases because it simply just works and then this felt compiler under the hood will take care of all that stuff. Is that still the case and it's felt five?
And so if you do have to understand a little bit more of the proxies, getters, and setters, because if you want to have like your own custom state function, right, like a create state function that contains multiple state values and is like fine grain reactivity,
you need to set, you need to use getters and setters if you're using a function for that or returning an object, right? But if you're using a class, you don't have to. So in, in spell five, it doesn't feel as simple in that regard. But if you are just creating a basic state variable, let's an object or anything like that, you're just creating it as is mutating it, whatever. So it's still mutation based, uh, behind the scenes or it's still mutation based in general.
It isn't as simple as the writable readable way they had it before, but I think it's better in a lot of ways. It's a little bit more explicit. There are times where it feels like I'm writing a lot more code, but I don't know if you ever got too much into really custom stores in Svelte 4. We have one for the audio player on this Intax site, and that thing's a bit of a beast.
And what I'm looking forward to most is converting that to a class and using that as some custom state is a class in Svelte 5, which it's not even though I did the migration. I didn't touch that code just yet. It's still the old way of doing it. But I think for big states, it feels a lot nicer.
Yeah, and that's actually a really good example of the difference between reducer-based state or like function-based state, you know, where you have an explicit function in order to interact with it versus atom-based state, which is our next one. So atom-based state is every, you can kind of think about it is if you've used U-state in React,
Kind of similar to that, whereas every piece of state is called an atom. And you break your state into many smaller pieces, right? So if you have a component that has a counter in it, an atom would be the actual counter. And you can, in order to interact with that, you don't simply just update it directly, but you have a set of functions to update it or to access it. Whereas with you state and react,
When you use it, the first item is the actual piece of state, and the second is the actual updater function. Atom-based state, probably the biggest ones out there are recoil in Jotai. Is that how you say it? Yeah, Jotai is fine. And the sort of difference between Atom-based and reducer-based is that Atom-based is more used for global state. If you want to have things that are sort of application-wide and there's generally no way to define
how it is updated. It simply is just your data and a function to update that state. Whereas with reducer based state, you often want to define your data as well as a list of functions and how you can interact with it, right? So if you have a list of comments, you may only say, you may add a comment,
that has these values in it, you may update a comment and you may remove a comment. Whereas with an atom-based state, you might just have an array of comments and you can do whatever you want with that. There's no way for you to really define how that is. Of course, you can make a function separately, but that's not part of the state management. That's just part of your application.
Cool. Oh, sorry. One more thing is the benefit, I forgot to say, is that one of the big benefits of using this atom-based state has to do with some of the annoying parts around rendering in React, which is, I'll just read it straight from the Jotai website. They say build state by combining atoms in renders are automatically optimized based on atom dependency.
So this solves the extra re-render issue of React context eliminates the need for memoization and provides similar developer experience to signals while maintaining declarative programming models. So one of the annoying parts about React is that if you want to have some data available to you in a component,
If you pass the if you have passed a fairly large state thing, especially if it's global state, if you pass that into a component, because you need that piece, anytime any of that state is updated, the whole component re renders. So the idea with Adam Bay state is that you create these little pieces and you simply just pass in what you need, or you pull out what you need from the store itself. And then it will be smart enough to only re render when that thing is needed.
But I always find that to be really annoying because, like, spelt as this, just figure out what I'm using and then don't rerender when I'm not using it. How about that? You know, and obviously it's a lot more complex than that, but, uh, yeah. I know. I know. I do. I think a lot of these, these state problems have come up from like ways to solve problems that were created by problems that were created by problems, you know, and it's like next thing, you know, you just have one thing to exist to solve a problem that something else created.
I don't know. I'm not smart enough to know if this felt way is scalable in the same way that the react way is. But one thing I really like about it is just, hey, you're not thinking about how many times is this thing rerunning or rerendering you're thinking about, is this value changed? Did this value change if it changed?
then update otherwise or update derived state or anything like that. To me that makes more sense, but what do I know? Next one is ways to hold state. You can hold state in all kinds of ways. We just talked about it a little bit in the mutation base where you can hold just state in a straight up object. A lot of times this
could be like a function that creates an object too. You have a function that creates an object, that object holds state. You can use getter and setter methods to set and get values from this. You can use methods inside of there to perform actions and modify the state as well, instead of just getting and setting it. That's pretty common, right? Instead of always doing get and set, you would have a dot increment method that would take the state value and increment it inside of that object.
Same thing with classes, right? With classes you have these methods inside of classes and again they're modifying this internal state within classes. It is funny how in JavaScript we tend to use objects for things that most other languages would just go straight to classes for just because classes are really newer and as in tactical sugar around objects anyways. But because of that I kind of stayed away from classes for too long and I
Man, I tweeted out the other day of just how Svelte Fi's been making me write a lot more classes lately. Not that it's making me. It's just the syntax ends up being a lot more concise without having to write getters and setters. And gosh, I kind of like writing classes. I don't know what's happened to me. Yeah.
I've always been a big fan of using classes for when everything needs to be self-contained. And almost always is when I'm writing something in Vanilla, where, like, for example, you are, in a lot of my courses, we'll do something where, like, we create a game, right? And that game will have internal state of what is the score, who are the players. And then we also have a whole bunch of methods to interact with that, right? You can increment the score, you can
add players to it, you can pause the actual game. That's another one I do as well, which is a possible set interval. You want to be able to run a function every 500 seconds, but you want to be able to also pause it and stop after a certain amount of time. If you want a little JavaScript exercise, that's a great one to do is a possible set interval that will stop itself after a certain amount of time.
and then you can expose all of the ways to interact with that via the class methods. You know what the best state management library out there is?
I do and I agree with this one so you can go. The URL. The browser's URL is the OG state management library because if you are filtering something, if you need to make something sortable, shareable, whatever, simply just put it in the URL and have your application UI react based on that. If you go to syntax.fm,
and you go to shows and you filter for different types of shows for how many shows you want for a sorting and what page you are on.
All of those things are not buttons or whatever to be able to do some sort of complex filtering. They're links. They're links. And we programmatically generate the links to those pages, but the state management for the show filtering is simply links and you can control
how you sort it, how many per page, what type of episode, all of that good stuff simply by visiting different URLs. And because now we have push date, where you don't actually have to refresh the page when you do this type of thing, it makes a really nice state management library.
Yeah, the best part about it is for me is that they're shareable, right? And if you think about it, if you take a very wide stance out your website or application, even just with a general URL or a general path in your application, you could really think about that as being state, right? When your website loads or even when your server gets that URL, it takes that and knows what page to load because that's the state of your website at that point.
So it is definitely the URL. And query params are really super underutilized for this type of thing. Next one I have here is index DB, local storage, or cookies. There's also session storage, which I don't know about you, but I almost find myself never using session storage. I don't know why. Maybe that's a gap in my knowledge. You know what? The difference between session storage and local storage is if you have multiple tabs open at once,
Is that shared across the tabs or is it unique for that? Because there could be a situation where you're working on two things, right? And you want to save that? Then that might be session storage. And also session storage will clear itself when you close the tab, which you may or may not want.
I know, I just don't, you know, maybe I think that doing the same thing. I rarely use it. I rarely use it if ever. But I think these often get overlooked as a place to store state. Even though people do often store state inside of cookies, you could think of like, I mean, you're accepting a cookie banner and you're saving that information and say, yes, I accept that we're tracking or not tracking cookies.
You know, that save of that state is being saved into cookies, most likely. And likewise, index DB. And that's a whole database there you can save stuff in. Same with local storage and you can pull that stuff up later. We use that to store like the current, like if you're listening to a syntax episode on syntax.fm,
At any given point, that timeline is updating and saving the state of that player into IndexDB. Then when we want to load the site the next time, we want to start you off in the exact same place you left off. We're capturing the state of that and keeping the state of the player in IndexDB and using that to control the interface when the page is loaded.
Uh, maybe one, one thing we haven't talked about here, but it's probably worth mentioning that you're talking about index DB is like, like sync engines, right? The whole local first being able to communicate with the server and possibly even the database, um, is, is often being attached.
to your state management, right? Yeah, let me even tell you, I've been using a platform zero, which I'm really excited about from the replica cache folks. I'm not gonna go deep on this until they fully release it, which I'm sure they will somewhat soon, or at least they'll release an alpha version of it. But when you work with something like that, where the cache, the front end cache of your site is one to one with your database, and I'll save locally, you really do start to have your database
be the state of your application. It's pretty dope.
That's wild. Form data is a way to hold state. I thought this was, I was like, is that a state management library? And it kind of is. So form data is an API in JavaScript to hold data because forms can be complex, right? You might have multiple inputs. You might have multiple inputs with the same name, right? Like, for example, if you have a pizza order form, you'll have toppings and you'll have multiple toppings that need to be stored.
So form data is a great way to store data, especially because that API is standard. It's standard in the browser. It's standard on the server. We're seeing a lot of remix, React Server components. I'm like, what are the other things? Form data is spelled.
Pretty much all of these libraries that expect data to be sent to it is being sent via form data. So and also form data has a really nice API. It has it's a nice setter methods. It has. Sorry, you said what? I said it's a nice issue API. I would wish I could just do form data dot property. That would take me a lot of. Yes, dot get because you have to use dot get and dot set and that has. And if you want to be able to loop over what is in your form data, it can be a little bit complex.
But there's methods for that. But it's pretty sweet. It does. It has a dot has method. So if you want to check if your value is in there, it's pretty nifty. So form data, kind of a way to hold state. Great way to send at least to send your state from your client to your server.
Yeah, for sure. The next one we have here is signals. Now, it's so funny. We've done so many episodes talking about signals, but whenever I see like signals in this kind of context, I'm just always thinking like, what exactly makes them special? Do you know what I mean? Like, what exactly makes them
interesting compared to, you know, some of these things. But a signal really is, it's a way of, it's like an observable state, right? Signals are a great way to define reactive state, meaning that instead of in JavaScript, if you think about it, like not even in terms of reactor or any frameworks out there, if you think about, I have this piece of data that
Other people may care about when this data is updated. I may care in other parts of my application where when this data is updated, you may want to store that data in a signal so that in other parts of your application, you can subscribe to that data. You can have an effect when that data has been updated. I always recommend to people, if you want to really understand signals,
There's kind of two ways to do it. First, go to the solid JS docs and just read through their signals documentation in like 10 minutes, right? It's probably one of the best implementations of signals. The other one is preact JS has this has a signals library, which is not tied to react. So if people always think, Oh, I'm not using react, it you can use it with vanilla JavaScript. So try to build a little application.
where when you update the data in vanilla JavaScript, anywhere that state is then used will be updated. And the Preact.js library, it's like, I don't know, it's like 200 lines of code or something like that. And it's a really simple implementation that really helped me understand it. And then of course we have, sorry, go ahead.
Oh, no, it's going to say, yeah. And also another great place to learn about this is the signals proposal because they're proposing to add signals to JavaScript as a whole. Now, it's only stage one, but the explanation is really good and it makes a great use case on why it even shows like computed properties, which we mentioned a little bit, but let's say you have a value that's derived from another value. This is a good way to use signals because again, it's if one value is changing, then we're able to
Modify another value based on that values change, right? You're having a computed property. And I know derived and computed properties are built in and baked into spelt and view. And honestly, there is a really great way to work because I feel like a lot of times we end up having derived state without even thinking about it. Oh yeah, absolutely. In the React world, you generally just like putting that into
your templates or you have a function that will will derive it for you. Then you have to worry about memoizing in. Yeah. Or if you want to listen for when that derive value is of a specific value, then you're getting into having to code like a custom use effect. So I'm pretty excited about this signal's proposal. I really hope that it makes it in.
Me too. Yeah, especially because it's how I've gotten used to working. So if that becomes baked, and since it's a lot of how you work in Svelte, I think their plan is with their new state, I think they designed it around once this does get into the language, which I think inevitably it will, that they could just remove a lot of their library code from that.
Another one that we don't often talk about, we did mention a little bit when we were mentioning local first is the server database can often store state. I think about user preferences are often like application state, right? Whether that's a user theme, whatever user preferences you have, those are more often saved in the actual database because you want those to persist from device to device or you want them to persist more so than just an individual client.
Yeah, and we talked about the sync engines. For example, in my course platform, we have some state which is where are you in the current video, right? You want to be able to do it. And then we also have state is how have you watched a list of all the videos and which ones have you watched and
how far along each of the videos are you and that allows us to render out a list of videos and check off the ones you've watched and show you a little progress bar on the ones that you have done. And that's interesting because that state must live client side because it has to render out the list of videos and where you are and update every
every video update, which is every five, 10 seconds. But then it also has to be saved server side, because if you come back the next day, you want all that data to be done, right? And that's where you get into needing a sync engine or just a function that pings that data to your backend and actually saves it.
Word. Global versus component state. We kind of covered this, but the idea of a global state is that something that needs to be accessed anywhere inside of your application. And then a component or local state is state that generally just exists inside of
that component. So if you have a contact form, you might just have local state inside of that contact form to manage the inputs, manage any errors that need to be displayed, anything else like that, right? Whereas a global state may be something about who is the current user that is viewing this type of thing, right? You need information about the user everywhere, or is the cart currently open, or what
video is the current user is watching. You may need that data globally. And if that's the case, you stick it globally.
Yeah, I know an example I had on this is my habit tracker. What month you're on, because it shows a month by month view, right? Several parts of the application need to know what month you're on at any given point, whether it is the list of habits or any sort of form you have, things that are not connected in the tree. This is like important state for the entire application to know. We're like, yeah, you have a modal or a drawer. That thing is local state. It's either open, it's closed, right?
And global state doesn't have to be application-wide. It can be something that lives just at a certain level. For example, if you wanted to show multiple months at once, then you would have two of those components, each with their own global-ish state, right? It's local to some component, yeah. That's a good way to put it.
Yeah, totally. Sharing state. How do you share state? There's kind of two ways you can do it. You can import and export the state into the components that you need. This is generally my preferred way to do it where you have like a store.ts file.
you create the store in there along with any other functions as to how to update it, and then anywhere you need that in your application, you will then import it. That's good for global state. The other way to do it is you inject it at the level that you need it, and then you can pass it down somehow. Either via context, in React is a common way to do it, or you simply use prop drilling, which is you pass it down via props to three levels, anywhere past two or three levels it,
starts to get a bit hairy. Yeah and this actually is something interesting if you're working with server side state. You can always have to be careful like if we have server side global state and it's being defined and created outside of the context of the current like loading flow that state could be created accidentally.
globally server side. So you do kind of have to pay attention to, is this state being created for this specific user in their specific path? Or is the state being created globally? And all of a sudden we're shoving sensitive information into this, this global store by accident that perhaps is available to the entire server, right?
Yeah. And that simply can be a variable that is scoped to your module. So you're a handler where someone visits a page on their website. Inside of that handler, you're going to have local variables, right? But if you touch a variable that is above that handler, but still inside of the module, those are shared amongst, at least in JavaScript, it's not the same in other languages like PHP, but
Those variables are shared and you might want that. That's great for sharing data between requests. For example, on the syntax screenshot tool that we use for the open graph images, we stick a global variable for the browser that takes the screenshot so that it's faster every single time that you use it. But if it's sensitive state, you don't want to do that, right?
Totally. Right. Yeah, absolutely. Let's talk about state libraries specifically. We've talked about a lot of these over the course of this episode, but if you're wondering about state libraries, it is funny that the way that this kind of works is that you have
a whole ton of state libraries for React. And then you have solid has their own signals-based implementation. View has their own state in kind of built-in state with Pina. And then you have Sfelt, which has its own state implementation. So when we're talking about state libraries, it almost has to be like, these are the state libraries for React, because I don't know why, but it feels like React is just
One of the ones where they have the local state figured out, but maybe like more advanced state, they're just like, all right, we'll leave it to user land. I mean, I don't know. Do you feel like you need a library, even before we get into the libraries and stuffs? In React, do you feel like you need a library beyond context and state?
I do because of the re-rendering issues in React. Ideally, you use state for whatever you want. You stick it in a global context, and then you can grab it out of context whenever it is that you need it.
But there's performance issues that come along with that. And I don't absolutely love the API for that type of thing. I'd rather just import it wherever I want. And you can get that API with a custom hook.
But I prefer the other options that are out there when I'm doing a little bit more complex stuff. So I'll give you an example. So I just rewrote my checkout for my courses. And I was like, hmm, I need something.
to hold all of the state for the checkout, right? Because there's going to be all the information that the user has typed into the boxes. There's going to be information about what course they're trying to buy. There's coupon code information. There's error and success messages that need to be displayed, all kinds of stuff that goes along with that. And to make it even harder on myself, I wrote the checkout in React,
But the actual website itself is just vanilla JavaScript. And I needed to be able to share the state between vanilla JavaScript and in the React world. So I actually opted to go with ZooStand after looking at all of them. And it's a pretty nifty one. First of all, because it works in vanilla JavaScript, which is something that a lot of times people need, right? You might not be using a framework. You might just be writing
some vanilla JavaScript because it's totally doable, but you still need the ability to listen for changes and to be a little bit more complex with how things work. So, ZooStand was my choice there. And the way that ZooStand works is that you create a store
with your data in it, and then you also define the updater functions that go along with it. So if you, their example is you have a store called a bear store, and you have how many bears you have, you have zero, and then you can also define increased population and remove all bear functions, which will increment or reset the number of bears in that store. I don't
Absolutely love the API because it makes you when you want to use one of those functions or you want to use a value from your store, I'm used to just like bear store dot bears, you know, I just want to reference it. But because of the way that rendering and react works, they say it's better to use this like weird callback function API.
where you simply just pick and choose the parts you want for that component. And the benefit to that is that you explicitly are telling it what you're using. But this comes back to my whole, can't you just figure that out for me? I know. I'm just using the variables. I know. I like Zustan the most in the React ecosystem.
I have it's funny I spent so much time in the react ecosystem that I used zoo stand in production code. I've used Redux in production code. I I never really got into mob X and mob X is kind of an interesting state because people like mob X and what's interesting about mob X is that there's also mob X state tree and like.
Just like with Redux, when you're talking about Redux a lot of time, people have their own Redux stack of all these different Redux, thunk, whatever stuff. And I honestly, the amount of things there, whether it's using just mobx or you have to use mobx, state tray, whatever, that conversation has turned me off so much from using that I never used it. Even though I'm quite sure that I would like mobx based on what I've heard about it.
But again, it feels too complex to me in that sort of way. And I'm sure it's just a skill issue or something. I haven't really, you know, it's not anything I've done before. But yeah, I don't know. I don't have too many thoughts about MobX other than I know people like it and I know people use MobX state tree a lot. Have you done any MobX work?
I have not, and I think it's just due to not necessarily needing that type of thing, right? The types of applications that people are building when they use Mobox or Redux or X-Date, X-Date Store, these libraries require a lot more boilerplate.
and I also just feel exhausted looking at the documentation for these types of things. Because like the simply setting up a variable that needs to be updated, wow, it requires its own file in like 40 lines of code. But I understand that that's not everybody's use case. People want to have full control over how this data is updated and how it's stored and how you can subscribe to it and all of that good stuff.
I certainly understand it, especially as you get into more complex applications. For example, their most highest sponsor for mobx is Canva, right? Oh, you're building entire Photoshop in the browser. Yeah, you probably are going to be thinking a lot about state management.
Yeah, I know. I do feel like, man, I feel like isn't mob X mob X is is sick. Is it not or is it observables? It's observable based. Yeah, it's observable based. So in just looking at the docs for observe or for mob X in general,
it looks like a slightly more complex version of what i'm using in spelt so for me i'm sure i would like it if i got past that initial feeling of wolf because i felt that way about redox and when i started using redox again like i definitely got it more i don't think i ever like truly was like yeah redox the best.
But I do understand the utility of it. I bet it's just a blindness, a skill issue. If you're using mobx, mobx, state tree, and you want to give us what the heck's the difference there? What are people actually using in mobx land? I want to hear about it.
Jotai, I'm my singer at Jotai. Jotai, yeah. Two syllables, Jotai. I explained earlier that Jotai is more of a primitive, and if you want just quickly get up and running, not to say that it can't be used for complex stuff, but especially for global state, Jotai is really good. It's similar to how React does use state.
And you can combine them together. It's a really nice API and often used for you can use Jotai and Zustan together. I believe they're by the same developer. Is that true? It's possible. I felt like they were at some point, but I guess I don't know now that you say that.
Yeah. Hold on. Let me, let me look this up. Seustan and Jotai are written by the same guy and, oh, even Valtio. This is another one I've not checked out as well. Proxy state management for vanilla and react.
And the same guy is working on Waku, which is a React Server component framework. So certainly, those are all worth worth checking out. And it's very clear that if the same guy has built three state management libraries that are very good, it's clear that there's different ways to approach and solve these problems.
Now, if you're listening to this episode, you know the answer to that. There's also xState, which we've talked a lot about state machines. And xState is a really cool platform because it basically allows you to have a system of working within state machines specifically. And it feels like something, again, that if you're building complex applications, xState feels like it would be a really great option to go with, especially if you're having a hard time wrangling.
like the actual state of things. And there's a great little visualizer that they have on the site and helps you build state with a visualizer. I do like all of that. What is this X-State store you have posted here? Yeah. So X-State store is from David K. Piano, and it's sort of a simpler version of X-State. I don't know if this is true, but I think a lot of people say that X-State is cool, but
I don't necessarily have those problems. I've said that many times, right? So xstate store is sort of a simpler version of that where you can get up and running. It's very similar to the reducer pattern that we just said, which is you create your store, you create your actual initial data in it, and then you can define the function update or functions that how you can interact with that actual data.
I tried it out when I was evaluating it for my cart checkout. But again, it just felt, there was two things. First, it felt like a little bit too much boilerplate code for me was not needed. And then the other one was I didn't like that when you want to run a function, like for example, they have an example where they have a donut store and they have zero donuts. And then when you want to add a donut,
But what I would like is donutstore.adddonut function. But what it actually is is donutstore.send pass an object with a type. And the type is a string of add donut. And again, I get that because it's very, very complex. But I don't like passing my functions as strings. And I know that people are probably cringing at me right now, but I just want a nice function that I can run. And Zuzdan gives you that.
You're just trying to function. Remember that song? Or a method I should be saying? No, what's that? Oh my god. What year did they come out 2020-2019? Maybe even older than that. Oh man, this is going to be really embarrassing if it's like 2015. Hold on. I'm just trying to function.
Oh, no. Oh, my God. Wes, this song came out 12 years ago. Oh, my God. 2012. 2012 in my mind will always be eight years ago. No matter how fast the things go, 2012 was eight years ago.
And you know, I should have known it was this long ago because they made a joke about it on workaholics and that show was at a peak in 2012 probably. Other state management libraries. There's another one I found called Easy Peasy, which is similar to Redux, but kind of a nifty
nifty little API for working with it. And it looks like it's in under very active development, a vegetarian state friendly state management for React. So this one looks pretty cool and has a whole like React hooks API with it. Yeah. And for view, we mentioned Pina. It's Pina. Pina.
Pinilla. Pinilla. P-I-N-A. No, it isn't. It's P-I-N-I-A, which I thought it was. Oh, yeah. You're right. Wow. This is a definitely a moment for me. I thought it was the same way that you were saying it was. But I do think a lot of people just use the built-in view state, but if you need bigger state, more modular safe. This is the community approved one, so to say. This is what people are using.
If you're doing a lot of fetching between APIs back and forth, doing mutations, being able to update data, TANstack query is one. I would consider that state management as well as a whole HTTP library, because what it does is you can give it a promise, which is
post to an endpoint to update some data or use a get request to load in data. And then you also get variables like loading variables and you can control how the data comes back, you can cache it, you can refetch it. So 10sec queries is kind of an interesting one because it's a state management library plus a whole bunch of stuff for working with the server.
the right well that is it that's a lot of stuff yes uh... that is state in javascript i know a lot of these things are react state and react but this is state javascript in general and a lot of these libraries that we did mention can be used uh... with vanilla as well as good in the part of show where we talk about sick
picks. I have a sick pick for you today and it was one because we just did our holiday sick pick episode. It's one that I actually had in that but I didn't have it as a normal sick pick so we'll do it again just in case that episode didn't appeal to you.
And I don't know about US, but I've been looking for men's body wash for a long time. I have not been looking for that, no. Yeah, I don't know why. But I had never found a lot of men's body wash that I really liked. I know a lot of it's just cheap garbage or whatever, or it just smells like normal. But I wanted something a little bit more like manly smelling. So I found this brand, this cremo cremo.
And they all are like branded after different types of like whiskey, whatever. And for the most part, you don't have to, it's not like it smells like whiskey, but I found this stuff to be really nice. Just about everyone that I've smelled so far has a bit stronger of a smell, but it is nice kind of like deep and smoky type of smell in general are those types of things rather than like
I don't know, just lavender and eucalyptus. So yeah, I've been a fan of this. I think somebody recommended it on Reddit and since then I tried a few different ones and they make shampoos and conditioners and stuff as well. So if you're out there and you're looking for a little bit more of like a manly dude smell, this is pretty good.
I'm a big fan of the Suavecito. They have a body wash, but they also just have like a bar of soap that smells amazing. And it's a huge bar of soap and lasts forever. So I've been having used that for a couple of years now. A big fan of that.
My kids don't love the smell. When you're a kid and you would smell some old dude with musky cologne, I wonder if it's similar to that. I love the suavecito scent that they have, but my kids don't love it.
I'm gonna stick pick a bento box that we got for kids so we switched from sending our kids to school with lunch pails to just sending them with a single bento box because what was happening is they would come home and like the school doesn't want you to use like.
any plastic bags or anything to give them their snacks in. So we were having like a thousand, a whole dishwasher full of these little cups that you had a wash. And it was getting to be a bit much. So we're like, what if we moved to bento boxes? And yeah, we tried a couple of them out, but they're all way too small to actually like, what are these kids eating? Like one cucumber and like half a sandwich. Like none of them actually fit a full sandwich in there.
So we finally found it's called an adult bento box which is silly because they are fantastic. It's three levels and they have rubber seals on them so you can send them with wet stuff or jello they're microwavable so they can pop the bottom off, throw it in the microwave at school. I searched for probably a year. My wife is like we need bento boxes.
I would be like, these all are awful. They're all way too small. And we finally found one that we're more big fan of. So I'll link it up. It's called the JS cares bento box with the three levels on it.
Wow. Okay. I'm going to actually even follow this up because Courtney has a three level bento box that she uses for her lunch, which is a bento. And I think it's really nice because it has like a thing for salad dressing and has a spot for a fork to get stuck in there too. So you can always have a
Yeah. A forq tensile. And I actually really like hers. I don't have one myself because I'm always eating here. We got the kids bento ones for the kids, but they are pretty small. We looked at them. We went to Costco and we looked at the bento. And the dividers are half the size of, they're way too thick. And then they got, some of them have like,
water in them so you can freeze them and it maintains cold. That's too heavy for the kids' backpacks. I do feel like ours are too small for stuff, because when I'm filling my kids' lunch box, I'm like, how am I supposed to get all of this stuff in here? Yeah, that was the problem we had. Because we looked at Costco sales, those bento ones, and they're no good. Yeah. Well, we use them. They're nice, but they're too small for sure. Yeah, definitely check this one out. Yeah, cool. Sick.
All right, shameless plugs check out the syntax YouTube channel. Subscribe, watch CJ just released a video on mapping software. So alternatives to Google Maps and really good video. You're going to want to check that one out. Yeah, super good. Cool. Well, this is as real as always. So we will see in the next one.
Was this transcript helpful?
Recent Episodes
853: The State of Frontend
Syntax - Tasty Web Development Treats
Scott and Wes discuss findings from the State of Frontend 2024 Survey, exploring trends in frameworks, rendering, state management, libraries, hosting, CI/CD, micro-frontends, package managers, JavaScript runtimes, TypeScript, browser technologies, PWAs, styling tools, testing, code editors, build tools, linting tools, operating systems, and future trends.
November 27, 2024
852: Cloudflare Tunnels
Syntax - Tasty Web Development Treats
Learn about Cloudflare Tunnels and their usage for secure remote server access, including setup, Apple Pay integration, and security considerations, with Scott, Wes, and Randy.
November 25, 2024
851: The Future of VS Code and Copilot
Syntax - Tasty Web Development Treats
Discussion between Wes, Scott, Cassidy Williams, and Harald Kirschner about new features in VS Code and GitHub Copilot, including custom instructions, UI/UX improvements, multi-line suggestions, prompt engineering, Copilot in Xcode, and the future of AI for various editors.
November 22, 2024
849: How to Pick a JS Package
Syntax - Tasty Web Development Treats
This Syntax episode guides listeners on locating and vetting JavaScript packages by using various search methods (npm, Google autocomplete, social networks) and evaluating factors like issue count, types, documentation, GitHub Insights, package.json file, and social proof.
November 18, 2024
Ask this episodeAI Anything
Hi! You're chatting with Syntax - Tasty Web Development Treats AI.
I can answer your questions from this episode and play episode clips relevant to your question.
You can ask a direct question or get started with below questions -
What was the main topic of the podcast episode?
Summarise the key points discussed in the episode?
Were there any notable quotes or insights from the speakers?
Which popular books were mentioned in this episode?
Were there any points particularly controversial or thought-provoking discussed in the episode?
Were any current events or trending topics addressed in the episode?
Sign In to save message history