React Component and State Management - JSJ 526
This episode is Part 3 of the Dan Shappir trilogy. Today, he’s laying out the deets on components and state management inside of React, plus some exciting developments coming later this year. In This Episode 1) Why you ought to know the “ideal” situation for React components (and how to get there!) 2) These new “front-end paradigms” that are going to CHANGE how we approach React and others 3) SUPER exciting developments coming for React in 2022
Show Notes
This episode is Part 3 of the Dan Shappir trilogy. Today, he’s laying out the deets on components and state management inside of React, plus some exciting developments coming later this year.
In This Episode
1) Why you ought to know the “ideal” situation for React components (and how to get there!)
2) These new “front-end paradigms” that are going to CHANGE how we approach React and others
3) SUPER exciting developments coming for React in 2022
On YouTube
React Component and State Management - JSJ 526
2) These new “front-end paradigms” that are going to CHANGE how we approach React and others
3) SUPER exciting developments coming for React in 2022
On YouTube
React Component and State Management - JSJ 526
Sponsors
Picks
- AJ- Dash Incubator
- AJ- Talks at Google
- Follow CoolAJ86 Live Streams:
- YouTube: https://youtube.com/coolaj86
- Twitch: https://twitch.tv/coolaj86
- Follow Beyond Code:
- YouTube: https://www.youtube.com/channel/UC2KJHARTj6KRpKzLU1sVxBA
- Twitter: https://twitter.com/@_beyondcode
- Charles- Dice Forge | Board Game | BoardGameGeek
- Charles- Top End Devs - for upcoming workshops
- Dan- Support Ukraine
- Dan- Interview with Senior JS Developer in 2022 - Youtube
Transcript
CHARLES MAX_WOOD: Hey, welcome to JavaScript Jabber. This week on our panel, we have AJ O'Neill.
AJ_ONEAL: Yo, yo, yo, convention live from the wonder desk, walking treadmill.
CHARLES MAX_WOOD: I'm Charles Maxwood from Top End Devs. And this week we also have Dan Shapir who's going to be kind of our guest and host and all that great stuff.
DAN_SHAPPIR: Yeah, for sure. Talking about interesting things, I hope.
CHARLES MAX_WOOD: Yep. Absolutely.
Hey folks, this is Charles Maxwood from Top End Devs. And lately I've been working on actually building out Top End Devs. If you're interested, you can go to topendevs.com slash podcast, and you can actually hear a little bit more about my story about why I'm doing what I'm doing with Top End Devs, why I changed it from devchat.tv to Top End Devs. But what I really want to get into is that I have decided that I'm going to build the platform that I always wished had with devchat.tv and I renamed it to Top End Devs because I want to give you the resources that are gonna help you to build the career that you want. Right? So whether you wanna be an influencer in tech, whether you want to go and just max out your salary and then go live a lifestyle with your family, your friends, or just traveling the world or whatever, I wanna give you the resources that are gonna help you do that. We're gonna have career and leadership resources in there and we're gonna be giving you content on a regular basis to help you level up and max out your career. So go check it out at topendevs.com. If you sign up before my birthday, that's December 14th. If you sign up before my birthday, you can get 50% off the lifetime of your subscription. Once again, that's topendevs.com.
CHARLES MAX_WOOD: So I'm trying to remember exactly where we left off with our previous discussions. We're still kind of talking React and React architecture and stuff like that, so.
DAN_SHAPPIR: I don't think it's surprising that you don't remember because as I recall, you weren't. You didn't participate, let's put it this way, in our latest episode about React. And we actually took that opportunity to talk for about an hour and a half because you weren't around to kind of limit our conversation and put us back on track. So we wandered all over the place, but it was a very interesting conversation, I think. And definitely, I think that anybody listening to this episode, and if they haven't listened to the previous two episodes about React, should go back and listen to them.
CHARLES MAX_WOOD: Yeah, absolutely. Well, it gives some context there. So yeah, so where did we leave off then?
DAN_SHAPPIR: Okay, so as I said, this will be our third and hopefully final episode about React. In the previous episodes, we talked about why React works the way that it does and how the virtual DOM or VDOM makes this method of operation possible. This time around, we will focus less on the VDOM and more on React's component model and also about its state management and lifecycle. So those are the topics that I would like to cover today. And you know React...
CHARLES MAX_WOOD: Awesome.
DAN_SHAPPIR: Yeah, for sure. Because React Places have very significant emphasis on components. They are its basic building blocks for UI construction. And in fact, React creators often take credit for bringing components into the mainstream of front-end development for the web. I know that this is something we can argue about, but that's the way they see it. And definitely with React, components are front and center. And as you may recall from our previous episodes about React, in the ideal scenario, React components are just functions, that's it, nothing more, and preferably pure functions. So they take the current applicative state as input parameters and output UI as the return value. And that's what VDOM effectively enables because their output is VDOM. And this makes them very easy to reason about, at least ideally, and also to unit test. And we also spoke about how VDOM does make this approach possible by representing the UI state as a hierarchy of simple JavaScript objects. So each such simple JavaScript object represents a DOM element or DOM node. So you might have a JavaScript object that represents a div, or an input, or a text box, or usually a div. And those are really simple JavaScript objects. They just have a field that basically just has either, if they stand for basic DOM elements, it's just the field that has the tag name as a string. If it's the DOM element that represents a React component, it will have a reference to that component function instead. And then it would have an additional fields that are a map of attributes to values, and then an array of its children. So, and in this way, it's kind of a hierarchy or tree of simple JavaScript objects. And that's essentially the VDOM. And JavaScript is really good at working with collections of JavaScript objects, obviously, and also testing tools can easily work with that, which makes unit testing, React component functions really straightforward. So that's more or less where we stopped in the previous episodes. And we also spoke about how React itself takes this VDOM and uses it to update the actual browser DOM using a process called reconciliation. It's kind of this different process. It looks at the previous VDOM that it had, the new VDOM that it just received, finds the differences between these two, and uses that to compute the most efficient sequence of operations to get from the previous state of the UI to the desired current state of the UI, and then applies these operations to the actual browser DOM, bringing it up to where it needs it to be. So this enables us as React developers to work with React in this kind of functional, pure functional way without having to deal with mutations because we kind of hand this task over to the React developers. We implemented this mechanism within the React engine itself. So far so good, because as I said, these are the things that we've actually talked about in those previous episodes. And what we also said is that while this is a very clean and simple approach, and it's great in theory, in practice, it gets more complicated or even much more complicated because in particular, React needs to enable components to maintain and manage their own private state. Otherwise they would just need to keep all the state in this kind of a common global state, and this is doable. Some people actually build their React applications this way. They, I don't know, they use Redux and put all the state inside of this global Redux store. So it's doable, but I don't think it's advisable because using, just using a global state in this way breaks encapsulation. And at the end of the day, encapsulation is a true, is a key requirement for true componentization. So if your data is accessible to...all the components, there's no encapsulation, there's no privacy of data, you know, what's your component model all about anyway? So what you really want to do is you want to have component level or component instance level private state. But how do you achieve that? Well, you know, if you think about it from the perspective of JavaScript, the language, and it's a language which supports object oriented programming, the obvious answer would be to put it inside objects. And actually, initially, that's exactly what React did. And when JavaScript introduced the concept of, or support for classes, React embraced it and started storing private state inside class field, class fields, actually. So it required, so basically when that happened, React kind of had two types of components. You had stateless components,were just functions like before, but then you had a stateful components, components that had their own private state, and those actually needed to be implemented as classes. And these classes would need to derive from a common React-based class and also to implement a special method called render. Actually, the only thing that was really special about it was that it was just called render. And the React-based class knew to invoke that method when it needed to get the VDOM for that component. And that render method worked instead of those simple functions that you could use with stateless components. So, so that's how React used to work. But you know, one, one important thing to note about that was that you didn't just put your private state in regular class fields. And the reason for that is that React needs to know when the fields change so that it can cause the component to re-render in order to update the UI in order to reflect the change to the values of those fields. So, you know, a field changes because a user interacted, let's say, with a component, which invokes some sort of event handler, which updates a field, but then React needs to know about it so that it can re-render that component using that new field value. Now, it is possible to spy on field Changes in certain ways in JavaScript like I don't know you could use a proxy or something like that So it is doable, but it makes the process more complicated kind of magic it adds overhead It's it's more difficult. Let's let's call it this way. So a much easier solution
AJ_ONEAL: Would you go into just what a proxy is real quick because I've heard that term before but I actually am not familiar with it
DAN_SHAPPIR: Cool. Can we save it for later because it's too deep of a rabbit hole if we have time Chuck, we could do an episode on overly complicated JavaScript features and talk about proxy as well. It's just that it's too much of a rabbit hole for now. Especially because React, unlike other frameworks, React just doesn't use it. So what React does do instead is that one of the methods, or put it this way, the base class that those classes would derive from implemented a method called setState. And so instead of directly updating fields to reflect private state changes, you would call setState to update the component's private state. There was actually this special field state, but you didn't get to it using this.state, instead you would go through setState. And setState, the important thing to understand about it is that it did not update that field immediately. What it kind of did is it scheduled an update for that field. So when you called setState, in fact, you weren't directly changing the state. You were telling React, I want the state to be changed in this way. Please do it, you know, when you can. And then also, we, we invoke the render method again to render that updated state. So, you know, setState is kind of, we talked about it in the previous episode as well kind of a misnomer, a better name would be something like, uh, please update state and schedule a UI re-render. But, but who wants to call something that that's kind of a verbose name. So they kind of went with set state instead, even though it doesn't actually set the state. So, and I know AJ that you really hate it when, when names don't actually reflect the actual operation.
AJ_ONEAL: That's true.
DAN_SHAPPIR: But it is what it is. So it was called set state. And I just explained what you did. So as I said, what it actually did is schedule state update and then we render. Effectively. That's what it does in any event, though. I really don't want to go too deeply into this, the details of the class based react components, because they're pretty much deprecated these days. You're not supposed to really use them anymore for reacts, uh, stateful react components. Instead, you're supposed to be using hooks. And so what are hooks? As I said, we briefly talked about hooks during the previous episode, but it was at the end of a really long episode and we didn't cover everything that I wanted to talk about. So let's talk about them again. So and what I do want to especially say about them, you know, it's really interesting. So React has introduced a couple of new paradigms, you might say, into front-end coding. The concept of the VDOM is something that I think React did first, at least for JavaScript. JSX is another thing that React introduced into front-end development and now is used by frameworks in addition to React, other frameworks as well. So Hooks is another React innovation, and I know that again, other frameworks have embraced it as well, and it's intended for cleanly maintaining state inside of functions rather than classes, and we're using state management strategies, and I'll explain in a bit what I mean by that. But the first question that we do need to ask ourselves is, why is it so useful for functions to be stateful components instead of just using classes? It's a legitimate question, I think. If we look, for example, at web components, that's the built-in mechanism that we now have in browsers for defining custom elements, they actually do use classes. So, you know, what's wrong with classes? So one advantage of using functions for both stateless and stateful components is that you can easily go back and forth as it were. You don't have to perform a significant refactoring of the code if you suddenly decide that, hey, this component needs to be stateful, so I actually need to change it from a function to a class, or, hey, I don't really need a state in this component anymore, so now I need to change it back from a class to a function. That can be a whole lot of coding. If we just, if you use functions for both, it becomes really easy. And in fact, as we will see, hopefully all you need to do is simply just add or remove calls to something like use state. And that's it. You add a call to use state, suddenly it's a stateful component. You remove the call to use state suddenly it's a stateless component. So that's all there is to it. Another advantage that hooks have is that they use closures to preserve state from rendering to event handling with class components, it was kind of a mixture of closures and class fields, which made it more complicated and, you know, kind of more difficult to reason about. And it's always better to be able to use a single mechanism instead of several mechanisms in conjunction, at least that's what I think. Also, and I think I speak for all three of us when I say that we generally all prefer closures over classes. Certainly when we can get rid of the JavaScript, of the use of the JavaScript this.
AJ_ONEAL: Yeah, I think that the term class is something that's a little bit overloaded because whether so there's the keyword class and then there's what a class actually is in terms of you're simply encapsulating some state as part of an object so that methods on that object are rather than being pure functions can have side effects to the state that's scoped within that object. And a closure is simply essentially a private object that is not visible to the outside. So everything that can be done with the class syntax is more or less exactly the same as the way you do it without the class syntax and the class syntax with the addition of the private. There are private methods actually now in JavaScript or is that still a proposal thing?
DAN_SHAPPIR: No, they are.
AJ_ONEAL: But with that you essentially get closures and classes. Sort of. And that's all that is. So it's. Tomato potato, I think that the functional closure approach is a lot easier to read, cleaner and more idiomatic, but they're exactly the same.
DAN_SHAPPIR: That's true and hooks kind of build on top of that, but on the other hand, they do introduce their own syntax and their own complexities and their own gotchas. So as we will see. So there is...a cognitive overhead in using hooks or switching to using hooks as well. So, you know, this thing doesn't come for free. This isn't exactly just a JavaScript closures. It's, it's more complicated than that. And that's actually what I'm going to talk about. So first of all, why are they even called hooks? Where does this name come from? The last time that we spoke about it, I think Steve brought it up that this name. It was kind of problematic for him because when he thought about the concept of what hooks usually mean, it was different than what he understood React hooks to be. So why did they actually call them hooks? And the answer to that is that these functions allow you to hook into React's own internal state management mechanism. React needs to maintain its own state. It needs to know, for example, where it is in the component tree where it is while building the constructing the VDOM. And so it kind of maintains its own state as it traverses that tree of components. And what hooks allow you to do is to basically hook into that mechanism so that React can hold on to values for you. And so you can put, so in effect, you're letting React manage your state for you. So...you associate a state with a component because React or with a component instance, because React knows when it's invoking the function for that particular instance, and so it knows to provide it with its, you know, state. And we talked about why React needs to have its own state mechanism, and that was, again, one of those things where in the ideal scenario of using a VDOM, maybe this needed...didn't have to exist, but because React wants to do kind of, let's say, partial generation of VDOM, only generating a portion of the tree, it needs to be able to go to a specific component and start from there. So it kind of needs to have its own state about where it is in the tree and which portions of the tree it's going to actually use at each point in time. So as I said, Hooks simply enable us to store our own applicative data inside of React's internal data structures, or at least a certain type of hooks allows us to do that. And one type of such a hook is, the simplest hook you might say, is called use state. And by the way, you will see that part of React's norma culture is that all hooks start with the word use. So it's always use something. And also when you define your own custom hooks, and again, something that we will hopefully talk about, you're supposed to also use that naming convention. So again, prefix the name of whatever custom hook you create with the word use. So use state is, as I said, is the simplest hook there is, you might say. You call it with a single input parameter, which is the initial value of a state that you want react to manage for you. So for example, let's say we want to implement a counter in our component. Let's say we're implementing a component that has a button, two buttons, let's say to increase and decrease some sort of visual counter. And we need to know the counter value. Obviously, again, we could put it in some global, but we don't want to do that. We want it to be private to that component, encapsulated within it. So we use state in order to...specify that we need to preserve this value, the value of the counter. And we call you state with a single parameter in this case, which would be just the initial value of that counter. So it might be use state, open parentheses, zero close parentheses, if we want the counter to start from zero, but obviously it could be any number or any other value that we would like. And it doesn't actually even need to be like a simple value like that. It could be a reference to a JavaScript object. And then you can obviously put whatever values you want in that object's properties. It's one thing to understand, which is kind of confusing to people seeing hooks for the first time. I think at least it was confusing to me is that that react component function runs multiple times. Usually every time you need to render that component and you call you state each and every time and you pass that initial value each and every time. But it actually only gets used the first time that you state is called because after that the value has whatever it is modified to and we will see how it is modified, but that initial value is essentially only used the first time. And then it's effective effectively ignored in all subsequent invocations of you state is that clear? I don't know when there's quiet. I'm concerned. Yeah. No, usually, you know, when I give talks, I can look people in the eye and kind of try to guess or gauge, you know, the level of understanding, but it's more challenging in this scenario. Anyway, it's interesting that because of this, UState also supports an alternative method of initialization that is instead of passing in a simple value, you can actually pass in a function that computes the initial value. And the benefit of that is that React will actually only call this function the first time. And that's useful when computing the initial value is expensive. So if you're just passing in a simple value, that's overkill. But if you're passing it, if you need to kind of compute the initial value, you obviously don't want to compute it if it's just going to be ignored. So having it, implementing it as a function overcomes this, but another degree of complexity. As I said, in any of the, either way react allocates a place for that value in its internal data structures. And afterward, it will just continue to use that place without additional allocations or initializations. Now useStake always returns a pair of values and it's implemented as it returns an array that has two elements. The first element is simply the current value as a value, not a getter just the simple value. So if it's a number, the first element in that returned array will just be the current number or string or whatever. And again, this is something that Ajay and I talked about because it's kind of confusing because some people do assume that it's a getter or something like that, but it isn't. It's just the current value. And then that value is used during the rendering or the generation of the VDOM. And what's useful also about that is because it's part of that functions closure. Now, if you have functions that are associated with event handlers on that element in the VDOM, then they see that value that they were generated for. Is that clear?
CHARLES MAX_WOOD: Yeah.
AJ_ONEAL: Yes. Sorry. I've got my mic muted.
DAN_SHAPPIR: Okay. We can edit all these awkward pauses out afterwards.
CHARLES MAX_WOOD: Yeah, we can.
DAN_SHAPPIR: Yeah, anyway, the second element is a setter function, very similar to the set state that we previously saw with classes. And it's used to update that specific value. So you would potentially use use state multiple times within that same component function. Each one of them, you would get back the current value and a set state for that specific value. So if we go back to the counter example, let's say you would get back the current value, which you might put in using the structuring. You would put in a variable, let's say, called counter. And the setter that you would put in a variable called setCounter. And then you could call setCounter with a new counter value. But it's really important to understand that, again, similarly to how setState worked with classes, When you call set the center function that's returned by you state, you don't change the value used in the current rendering operation. Instead, you basically tell React that, hey, I want to schedule a future render with that value. So again, even though it's called a setter, it's actually schedule an update and a rerender. So as I said, the component function uses the current state value to render the UI. It also, as I said, often associates event handlers with the elements in that UI. And these event handlers are functions that are declared, often they're just arrow functions. So they're declared within that closure, so they see the current value and they see the setter. So they can use the current value to do whatever, and they can also use the setter to update that value. And when that value is updated, then React will eventually invoke that function again with the new value. Now, an interesting consequence of this is that if we call the setter directly from within that component function, which is kind of silly, but obviously you can do it, what you will end up with is effectively an infinite loop, because you would render the component with the current value but then immediately tell React to invoke the function again and again and again every time with a new value. Now this sounds problematic, but it kind of makes sense in this sort of a perverse sort of way, because there's no point in rendering for the specific value if you're going to immediately change it to a different value. So it kind of makes sense that the UI gets overwritten. Now two more things about useState. As I mentioned, first as I mentioned, I think before, usually it's used with destructuring to get at the values. Usually I don't see people actually explicitly using the array. They just destructure it into two variables. Usually also it's kind of recommended to use cons for that. I know that Edgy doesn't like it, but it kind of makes sense in this case because it kind of highlights the fact that you're not supposed to directly modify the returned value but instead use the setter function to change it instead. So you're kind of forced, so having it be immutable makes sense and you know, you do that using the const keyword in JavaScript. Secondly, another interesting thing is that instead of passing a new value into the setter as a parameter, we can also pass in a function instead, kind of like what we did with useState itself. And this is a function that gets the current value as a parameter and its return value is supposed to be the new value. And without going into too much details, just to say that this can be useful because such a function can be independent of its containing closure, because it doesn't just see the previous value and then changes it accordingly. So the same instance of that function could be used throughout the component's lifetime. It doesn't need to be recreated by the JavaScript engine every time the closure changes. Now, suppose we want to store, let's say, three values instead of just one. You know, how would we go about it? Well, the easiest solution is to simply call useState three times within the same component function. So you call useState once to create the first value, useState again, the second value, and then again, useState to create the third value. But how does React know which part of the internal state to return for each call of useState? And the answer is that useState is order dependent, which is kind of unnatural. At least it seemed unnatural to me when I first saw it, but it makes the API a whole lot simpler. Otherwise we would have needed to pass some sort of an ID in to identify which value we want to get. So instead they just made it order dependent. And understanding this fact is critical for working with hooks because otherwise you're really in for a world of pain. And that's because you must call useState every time in the component function in the exact same sequence. Otherwise, you will mix up your state values and setters. And also, this is why you must never use useState from within conditional blocks or loops. If you put it in a conditional block, you can get a different order depending on whether or not the condition is true or false. And if you put it in a loop, Well, you'll be getting a new state value and setter on each loop iteration. So for this reason, hooks really need to be listed at the top of the component function before the implementation of the function logic, kind of like what you do with the imports at the top of the file. And if people remember our whole discussion that we had about bars and hoisting and stuff like that, it's kind of like you're supposed to manually hoist all your hooks to the top of the function. Otherwise you can get into trouble
AJ_ONEAL: and that's that's because of the magic side channel state that it carries
DAN_SHAPPIR: That's because it's just identifies that you know The first you state goes to that entry in the internal data structures The second one goes to that entry inside the internal data structure and the third goes to that so it identifies Which values associated with which hope based on their order not based on some lookup or something like that? Another thing, which I don't know, maybe it's obvious, maybe not, is that hooks can only be used, or actually more appropriately, can only be created within component functions or inside functions that are invoked from or by component functions. You can't just create a hook in the global namespace or some function that has nothing to do with React. And that's because Again, you're using React's own internal data structures to store the values and you know, you can't call hook when you're not inside React, for example. But we will see that pulling the hooks out of the component functions themselves and into functions that are invoked by the component functions can actually be a very powerful mechanism for reusing state management logic and this mechanism is called custom hooks. But before I describe how you build your own custom hooks, let's look at a few more examples of hooks that React provides out of the box. For example, there is another hook called use reducer, which works really similarly to Redux. Effectively, it was inspired by Redux. So instead of...
CHARLES MAX_WOOD: I was gonna say that sounds like a Redux.
DAN_SHAPPIR: It's exactly a deal, right?
CHARLES MAX_WOOD: Reducers is what they call them in Redux.
DAN_SHAPPIR: Exactly. So instead of, you know, with useState, you just provided that single initial value. With useReducer, you actually provide two parameters, the initial value, but also a reducer function. That's a function that's supposed to take a state and an action and use that to generate an updated state. And I won't go into the details because, again, that's...way beyond the scope of this conversation, but that's essentially what it does. And this useReducer also returns to, it has two return values, again, as an array of two values. The first, again, being the current value, but the second, instead of being a setter, it's a dispatch function. Again, you know, going back to this similarity to or the parallel to Redux. And dispatch function is what you use to provide an action to the reducer to compute the updated state. And like the useStateCenter, the dispatch also instructs React to invoke the component function again to render the UI from the updated state. So the dispatch uses the reducer to update the state and then invokes React to render that updated state. So again, I won't go into too into more details about exactly what reduces are and what their benefits are and why even use them. It's a it's a It's an interesting topic, but it's way beyond the scope of this discussion which is going into a lot of details as it is Oh another another interesting hook function that I want to mention Is use memo. It's another built-in hook But with a very different purpose from the two that we proved that I just described This one is not about preserving state and tree and triggering a re-render when that state changes. Instead, it's intended to reduce the computational overhead of generating the VDOM inside the component function. So think about it like this. React itself uses diffing to determine what is changed in the VDOM in order to reduce the overhead of real browser DOM updates. UseMemo lets you use diffing to reduce the overhead of computing the VDOM to begin with. So that's its purpose. It takes two parameters, a function used to compute the value that you want, and an array of input values that that function depends on, or the inputs that are the inputs to that function. The first time this hook is used, React just invokes the function, but then it stores both the computed value and the array of inputs and returns that computed value. But the next time you use that hook, it first compares the array that it receives to the stored copy. If the stored copy and the new array are the same, contain the same values, it will just return the stored result. Otherwise, it will recompute it. So this way, you avoid recomputing values when their inputs don't change. And again, the purpose here is to reduce the overhead of computing the VDOM within that component function, it has nothing to do with actually invoking that render function itself. And for that reason, useMemo only has a single return value because there's no setter or anything like that. It's just a way to kind of memoize a value or computation of a value. That's it.
Hi, this is Charles Max Wood from Top End Devs. And lately I've been coaching some people on starting some podcasts and in some cases, just taking their career to the next level. You know, whether you're beginner going to intermediate and intermediate going to advanced, whether you're trying to get noticed in the community or go freelance, I've been helping these folks figure out how to get in front of people, how to build relationships and how to build their careers and max out and just go to the next level. So if you're interested in talking to me and having me help you go to the next level, go to topendevs.com slash coaching. I will give you a one hour free session where we can figure out what you're trying to do, where you're trying to go, and figure out what the next steps are. And then from there we can figure out how to get you to the place you want to go. So once again, that's topendevs.com slash coaching.
DAN_SHAPPIR: The final built-in hook that I want to describe is called use effects. I'm always kind of thrown off by it because when I see the word effect for some reason my brain goes to a special effect. But in this case, it actually is called that way.
CHARLES MAX_WOOD: Oh, there you go.
DAN_SHAPPIR: Yeah. But in this case, it's actually called this way because it's meant to encapsulate side effects. So it's useEffect. The effect comes from the term side effects. But it's really worthwhile asking, what are even side effects in this context? So for a React component function, a side effect is any operation that it needs to perform that isn't directly about generating the VDOM. So if that React function, in addition to generating the VDOM, also needs to do something else, affect the outside world in some other way, that's obviously a side effect that should be encapsulated within useEffect. And I'll give an example. Let's say we want to implement a component that is a clock that just shows the time and that time updates automatically every second. So the trivial thing is to put the current time inside use state, and then every time we update the time by calling set state, that will force the UI to update to reflect the new time. But the question then is obviously what actually calls the setter every second. So we can use a set timeout inside the component function itself to invoke the setter, let's say after a second. But there's no guarantee that React won't decide to just call that method again, because the component function again. And then you would have two setTimeouts for no good reason instead of just the one. Is that clear what I'm trying to explain?
AJ_ONEAL: So. Yeah, I think so.
DAN_SHAPPIR: So, you know, having to setTimeouts is not the end of the world. It's not that bad, but. There are other operations where these things could be really significant. For example, if you have a side effect that performs some sort of a network operation or a database operation, in those cases, you definitely don't want to perform this operation when you don't need to. And useEffect solves this problem and also creates a clear separation between the component function's pure rendering part and performing the required side effect. So useEffect takes two parameters. The first is required, and the second one is optional. The first parameter is a function that React invokes in order to perform the side effect. That function is only called after React finishes performing the reconciliation into the browser DOM. In other words, the user will see the UI update before the side effect executes. And it also means that the side effect code can actually access and use the updated browser DOM. So for example, you can use the side effect, let's say to trigger a CSS animation on the DOM element that you just created. And you know that the real DOM element will be there because React finished its reconciliation before it invokes all these side effects. The second optional parameter works kind of like use memo. It's an area of values that the side effect depends on and is only executed if at least one of these values has changed. And if we go back to that setTimeout example, we can use this to schedule another timeout only after the state value has changed. So the array in this case would contain the current time and only when the time changes we would schedule another setTimeout. So a final note about useEffect is that some side effects require cleanup operation, and Use Effect actually provides a mechanism for that as well. For example, let's say you're creating a web socket, and you want to close or clean up that web socket when the component is removed from the DOM. You can do that. I won't go into the details of how it works exactly, but that's also a part of the functionality that's provided by Use Effect. Also, there are an additional number of built-in hooks, but there are mostly just variations or enhancements to the four hooks I've just described. Some of them do have additional interesting functionality, but there's a limit to how much API I can describe verbally without going to a whiteboard or something. I think I'm stretching the medium as it is. Anyway, hopefully our listeners are able to follow. The final aspect of hooks that I want to explain and I mentioned before is the concept of custom hooks. So the various hooks that I've described so far were fairly low level and general purpose. You had the hook for managing a simple value. You had a hook for doing side effects. But let's say I want to have multiple side effects or I need to have multiple values. Or let's say I have all sorts of complicated logic that ties all of these operations together. Now, obviously I can just put all this logic inside the component function, but there are two problems with that approach. First of all, it makes the component function itself much more complicated, which makes it more difficult to reason about, to test, et cetera. So that's one problem with it. And the second problem has to do with reuse. I mean, each component might have its own state values, but...different components may want to share the same, let's call it state logic. So there's the question of how to share similar logic or logical pieces between different components. Now React had a lot of, they really, this is something that React creators really thought long and hard about and they used several different mechanisms along the way they had at the beginning, they had something called mix-ins, and then they had higher order components. Again, I won't go into the details of what these are, because they're kind of being deprecated in favor of custom hooks. So what are custom hooks? Basically, you take a portion of that function, of that component function that uses hooks, and you break it up to a separate function that you call...from your component function. And that's essentially it. And because that function is called directly from the component function, and consequently shares the same React state, it can also use the simple hooks. And in fact, this allows us to group a sequence of hooks operations together. And as I said, the best practice for them is to prefix their name with the word use, but basically they're just functions that use other hooks. That's all they are. And they can only be called either from component functions or from other custom hooks. That's it. Because again, they need to be able to hook into React. So for example, we could have a custom hook called, I don't know, let's say, useFetchData, which would perform a fetch operation from the server and update the state accordingly, or alternatively, cause an error to be displayed by the component that uses it. And we could use this hook from multiple different components. Now, what's really cool about this is, as I said, that the same custom hook could be used from different component types, and that is different component functions. Now, as I said, obviously, each such component will have its own state data, but the functionality is now shared between them. This, of course, is not that surprising when you understand that custom hooks are basically just functions. So, you know, it's not such a big deal at the end of the day. We are reusing functionality by putting it in functions and then calling these functions. So, at the end of the day, no magic here, but because at the end of the day, the whole purpose of functions is to reuse functionality. But I think it's still cool how this all ties together, at least in the context of React. And that effectively...concludes my description and explanation of React Hooks and hopefully you made it out alive. Any questions about anything that I said about Hook? I know I threw a ton of information your way and our listeners as well. I think you're shell-shocked.
CHARLES MAX_WOOD: We've talked a bit about, well, I'm just trying to figure out exactly where to go with my thoughts. I mean, I kind of co-hosted React Roundup for a little while and we talked a bit about... React hooks, but it'd been a while since I'd really been on a podcast where we were actually discussing them So but it makes sense I mean in the sense that you you have kind of this way into the components and Kind of a desired way to interact with them That's you know, you could standardize across the same component that can be reused across your entire app
DAN_SHAPPIR: Exactly. So so yeah, you're definitely supposed to be to use custom hooks when you're implementing anything except really trivial or really component specific logic. Just take that sequence of logical operations that use hooks and just break it out into a separate function. Now, again, similarly to the built-in hooks, because the custom hooks usually also use built-in hooks, they are order dependent. So again, you, you kind of want manually hoist them to the top of your component function and not have put them inside the conditionals or loops or stuff like that. Just put them at the top of your component function. So at the end of the day, a component function might look like a call to... A stateful component function might look like a call to one or more custom hooks followed by the return of the JSX that uses the values that it got.
CHARLES MAX_WOOD: Yep.
DAN_SHAPPIR: Now, as I said, this essentially concludes my description and explanation of React hooks. But again, I want to mention how cool I think it is how much innovation React has brought into the JavaScript ecosystem. Now, you know, we might like some of this innovation or we might dislike some of the innovations, but undoubtedly they've shaken things up. So I mentioned before, they brought in the concept of VDOM, they brought in the concept of JSX. Now they brought in hooks. Interestingly, React has impacted the JavaScript language itself. For example, the fact that you can apply the spread operator to simple JavaScript objects is something that JavaScript itself actually got from React. React is really impacting the JavaScript ecosystem significantly. And this whole concept of having statefulness in functions instead of classes is now something that I'm seeing other frameworks adopted as well. Some of them using some of them even using hooks, some of them using other mechanisms and set. Now, before we finish,
CHARLES MAX_WOOD: I'm looking forward to Angular hooks.
DAN_SHAPPIR: Yeah. The funny thing is I'm now working at a company called next insurance. And, uh, we actually, at least for now use Angular for a lot of our front end. So I'm actuallyabout to delve into learning Angular. So maybe you can expect a couple of episodes about that as well.
CHARLES MAX_WOOD: Yep, absolutely. And we have an Angular podcast as well .
DAN_SHAPPIR: So if you're, yeah, be a guest on that'd be cool. Other podcasts. Sorry. Anyway,
CHARLES MAX_WOOD: there we go.
DAN_SHAPPIR: Yeah, for sure. Before we finish. And I think we have a bit more.
AJ_ONEAL: I couldn't find the unmute button.
DAN_SHAPPIR: What did you want to say?
AJ_ONEAL: I was going to say, I'm going to be very interested to see. Uh, once you've seen the light of how simple and declarative a UI can really be, I'll be interested to hear how much you love angular.
DAN_SHAPPIR: Yeah. Maybe.
AJ_ONEAL: I mean, angular is a little bit of a beast in terms of it's over engineered, but gosh, compared to react, it's a dream.
DAN_SHAPPIR: Again, react is as simple or as complex as you make it out to be. I mean, the fact that the framework might be really complicated on the inside doesn't change the fact that from the outside looking in. It's basically trying to be as close as possible to the concept of view pure functions for generating user interface state in UI out.
AJ_ONEAL: It's just in general imperative is easier to read and understand. But in the case of HTML, I prefer the declarative approach and angular slash view. They just nail it as being really simple declarative syntax that is unencumbered with JavaScript and logic. And, you know, it's just, it's a lot easier. Read. Anyway, I'll shut up.
DAN_SHAPPIR: No, you don't have to.
CHARLES MAX_WOOD: Nope, nope, it's all good.
DAN_SHAPPIR: You're here for a reason, AJ.
CHARLES MAX_WOOD: I mean, this is, yeah. That's the whole point, right, is we can have the conversations about, okay, my experience dictates that maybe this approach is better than that approach.
DAN_SHAPPIR: By the way, if you're going declarative, I have to remind everybody of the episode that we had about HTMX. So if you want to really go declarative, and if that is...let's say flexible enough for your needs, then that really makes your UI declarative. Hardly any JavaScript at all. It's all just HTML. Do we have a bit more time?
AJ_ONEAL: That was modern hypercard, wasn't it?
DAN_SHAPPIR: Yeah, that's the guy that kind of-
CHARLES MAX_WOOD: Do we have Wawa?
DAN_SHAPPIR: That's the guy that's kind of still in love with hypercard. Yeah, the hypercard aficionado. But I think you created a really, really cool system. So-For our listeners, if you're not familiar with HTML, definitely go back and check out that episode. It's really interesting. It will blow your mind. Do I have any time to talk about some of the things, of at least one or two things coming down the pipe in the context of React 18?
CHARLES MAX_WOOD: Yeah, I think we've got about, what, 10 minutes? Okay. And then I think we need to do picks because I have a hard stop at noon. So let's do one.
DAN_SHAPPIR: I'll talk about React server components. So that's a really interesting one, I think. And it simultaneously...tries to make things simpler and again makes them a whole lot more complicated on the inside in order to do that. So what are React server components? You may recall that in the previous episode on React, I explained how server-side rendering, or also known as SSR, speeds up the load time of a web page that uses React, or at least the experience of a person visiting a web page that's built using React. And that's because SSR uses the same React code as a templating language on the server side. You might have heard the term isomorphic code. That means running the same code, both in the browser and on the server, which is possible because your server uses Node, so it supports JavaScript, and you're creating VDOM instead of browser DOM, and VDOM being just simple JavaScript object work just fine within Node. The only difference is that instead of using that VDOM to update the actual browser DOM. On the server side, what we do with it is that we serialize it, let's say, into an HTML string, which we then send down as the HTTP response from the server to the client. And the benefit here is that the browser, which gets this HTML string, can just use it to display the user interface before any of the JavaScript code actually downloads or runs on the browser side. Because if you do everything in client-side rendering, then you obviously need to first download all the JavaScript and all the data before you can actually render the UI. And as I said, as I explained, SSR overcomes this challenge. But there are problems with this approach. For example, I explained that you still need to download all the React code and all the data that was used to generate the VDOM on the server to the client side because you need to perform an operation called hydration, which is effectively creating the virtual DOM that matches the HTML that you have. So you built a VDOM on the server, used it to generate HTML, sent that HTML to the browser, the browser rendered that HTML, but the browser doesn't have the VDOM. So how can it do the diffing going forward? Well, you need to download all the JavaScript, all the data, to create the VDOM so that React can kind of hook up its event handlers to the HTML and then do all the diffing going forward. Hopefully that's clear. And if not, then listen to our previous episode where I explained this in much more detail. So you can do all this hydration after the HTML or the UI is displayed, but you still need to do it. And if it takes a long time, then what you end up with is an unresponsive user interface. Because you displayed all the HTML, so let's say the buttons are there, the menus are there, everything is there, but until you run that JavaScript on the client side, the event handlers aren't hooked up. So if you click on something...
CHRLES: Right, they're just queuing up events to run in a minute.
DAN_SHAPPIR: They're not even queuing up the events. The JavaScript is not there. Oh. So you're basically potentially, look, you know, you can overcome this by actually handling some of the stuff in the HTML itself. So for example, you might have a form and the form just submits before you intercept the submit button. But if you're dependent on JavaScript to actually do something until that JavaScript, you know, is there, it won't do it. React components aim to solve this problem by running certain component code completely on the server side. And the way that React accomplishes that is that instead of having the actual component code, the function that generates that component, having to download it and run it on the client side with the appropriate data, React just executes its own special stub. And that stub can send data, such as user interactions, back to the server to be handled on the server side and then gets back as responses, the VDOM to use to update the user interface. So instead of performing all these operations of updating the VDOM using client side code, you set react and send the parameters as it were to code that's running on the server and then get back the response as serialized VDOM and use it in the client. Now, obviously it's kind of complicated to implement that because you're introducing latency, it needs to be asynchronous, stuff like that. So it's definitely not trivial, which I guess is one of the reasons that React 18 is taking such a long time. But once we have that, it means that you can avoid having to download the code or the data for certain components to the client side because they run completely on the server side. Now, obviously there's associated cost because there will be a network delay, a round trip on every update to such a component. So you probably don't want to use React Server components for highly interactive UI elements. But the cool thing about them is that you can actually mix them with components that are processed on the client side. So you can have a server side component wrapping a client side component, wrapping a server side component, wrapping a client side component. So it's you know, kind of automagically works. And being select...
CHARLES MAX_WOOD: Right.
DAN_SHAPPIR: Yeah, so it effectively enables you to selectively keep certain code and data completely on the server side and just send VDOM updates down the wire. And that can be a huge advantage in some cases. And if you kind of think about how this will work when it's coupled with edge computing, then when the latency becomes really low...then it becomes really interesting. And I think that Remix, I think, is playing around with stuff like that. This functionality, as I said, is part of React 18, which hasn't been released yet, but I think they have a release candidate. I don't remember if it's a beta release candidate. Either way, it's supposed to be pretty close, and you can definitely play around with it if you're building coding or building stuff in React. And this is another example of an innovation being introduced by React also made possible by VDOM because using VDOM is what makes it possible to send these updates down the wire after the UI is already rendered. Now you might say again, what's the magic here? This is at the end of the day, this is just making Ajax calls to get instructions of how to update the UI and you'd be right. But the fact that you can mix in the JSX, server side components and client side components. And you don't need to think about which runs where is a pretty powerful paradigm.
CHARLES MAX_WOOD: And yeah, it looks like it's in beta right now.
DAN_SHAPPIR: Yeah. I think I actually have not had a chance to play with it. I've looked at some of the demos. I looked at the videos. It looks pretty cool. I, it might be an overkill in some cases. Uh, I think we talked about it before the show that in many ways react was created for what Facebook needs, which is usually a lot more that most websites need. So you might say that the server side components are an overkill if all you really need is just to do some UI generation on the server side. But you get it kind of for free as part of React. So there's that.
CHARLES MAX_WOOD: Yep, absolutely. Well, we're kind of at the point where we need to do PIX.
DAN_SHAPPIR: And I'm at the point where I'm done. So PIX is good for me.
CHARLES MAX_WOOD: All right, well, let's, yeah, let's do it.
Hey folks, if you love this podcast and would like to support the show, or if you wish you could listen without the sponsorship messages, then you're in luck. We're setting up new premium podcast feeds where you can get all of the episodes released after Christmas 2020 without the ads. Signing up will help us pay for editing and production, and you can go sign up at devchat.tv slash premium.
CHARLES MAX_WOOD: AJ, what are your picks?
AJ_ONEAL: Just finding the mute button again. Okay.
DAN_SHAPPIR: Oh, that's a good question.
AJ_ONEAL: So I think I've picked this before, but I've been working with Dash Incubator and and dashes dash stands for digital cash. It's a international digital currency aiming to be like us dollars and euros and pounds and all that but but cross borders and there was something really interesting that happened two nights ago when I was when I was working on a demo merchant app. So one of the ways you can pay is just scan with a QR code and the fees are incredibly low. They're less they're less than US dollar cent. So it's it's in micro dash is what the fee is. So mill a dash is basically down in the range of cents. And then micro dash is down below that right. And it it occurred to me, one of the reasons that we have these kind of master slave Preemium models where you sign up for something and then sell your soul is because the transaction fees You know, user costs round down to zero and the transaction fees round up to a lot. So 30 cents plus 3% plus additional overhead fees for whatever framework or platform you're going through to do the payments. It typically ends up being 10% fee or more when you're trying to transact something. But if you could just pay Milidash for your own accounts and your own services and that sort of thing, you wouldn't need a Preemium model because it's not hard to pick up an app, scan a QR code and pay 10 cents equivalent for a month of service to something you know, and I don't know, that just that just got me thinking about the potential for the future of the web. And I'm changing some of my opinions around not all digital currencies, but at least things that are like Dash that are really trying to be a currency and really trying to solve a problem, not just do some sort of pyramid investment scam scheme. I'm I'm really liking it. It's really similar to some ideas I had back in the Dappley days around what payments ought to look like for for the internet. And so I think I think I will probably just pick that this go around. And then as per usual, if you want to check out creeds of craftsmanship, that's where creeds of craftsmanship.com that's where I'm aggregating the best talks that I find actually I should pick these. I just added some new ones this past week from talks at Google, which is the new rebranded Google tech talks. They keep on changing the channel name, I guess as it gets under new management and whatever. But the new, the new channel is called talks at Google and there was the creator of TCK TL or tickle. What's the programming language that's known as tickle. I forget what the acronyms are, the letters are for it, but he gave an excellent talk. He's now a professor at one of the Ivy league schools for software engineering and His, his lecture was just amazing. And I'm really interested in getting his book now.
DAN_SHAPPIR: The language, by the way,
AJ_ONEAL: I added it to creeds of craftsmanship.com.
DAN_SHAPPIR: The language by the way, is called TCL. TK is a graph UI library or something like that built on top of TCL. It's a real cool. It's a real,
AJ_ONEAL: so he developed one of those.
DAN_SHAPPIR: It's a real cool programming language. It's kind of lispish, but everything is a string. Something like that.
AJ_ONEAL: Well, he shared some regrets about it as well. But he just talked about he I mean, he's an old guy. He's got lots and lots of experience under his belt. He's seen lots of students lots of industry experience, not your typical college professor. Anyway, there's that and there was there was a couple other talks. One of them was algorithms to live by I don't know if I added that to the list because it's not as much about programming is it as it is about life hacks that you can you can apply computer science, science algorithms to life hacks like buying a house or marriage. And kind of guarantee that you're going to get the best possible statistical outcome. And I thought that was pretty good. And then, you know, if you want to follow me on Twitch or on YouTube for the live streams, it's cool age 86. And then the lesson style content and the little Q and A clips and stuff that come out of that are going on beyond code bootcamp. So there's that.
CHARLES MAX_WOOD: Awesome. Alright, Dan, what are your picks?
DAN_SHAPPIR: Okay, so I have two picks for today. One pick that is, I don't know, let's call it sad or distressing. And another pick which is really funny, glad. So I'll start with the sad one, and that's the ongoing situation in Ukraine. So I picked it last time, but you know, it keeps on happening and getting worse. Hopefully this will somehow be resolved by the time that this episode airs. I really hope so. I'm crossing my fingers. But...So far, I'm not seeing the end. To be honest, I really don't understand what Putin's end game is. It's really distressing for me because the previous company that I worked for, Wix, has offices in several cities in the Ukraine. And I actually visited Ukraine several times, and I know people there. It's a lovely country with lovely people, and it's really distressing to see people in a city that you've visited and toured preparing Molotov cocktails and getting bombarded. It's really sad and really distressing and I hope that it ends soon in a positive way. So that's my first pick. The second pick that I have is this super funny video that I also shared with you guys. It's from a channel called Programmers Are Also Human and it's called an interview with a senior jazz developer in 2022. And it's hilarious. Obviously there will be the link in the show notes. So after you finished listening to the podcast and you know, all the serious details about react, go and listen to that. And it basically pokes fun in a lot of ways to everything I've said during this entire podcast. I highly, highly recommend watching it. I laughed through the entire video and those would be my picks for today.
CHARLES MAX_WOOD: All right. All right. I'm going to jump in with picks. The first one is the board game pick. This one, I guess there is a board on it, but it's a dice game really. It's called Dice Forge and what you do is you, anyway, you collect resources. I'm trying to think the best way to describe it. You collect resources that allow you to purchase different cards and the different cards enable you to change the faces of the dice that you're rolling. So as a whole bunch of dice faces that are
DAN_SHAPPIR: So it's kind of like the Cones of Dunshire, but without the cones. And let's see who gets my reference. I don't know that I've ever played that one. It's not a real game. It's a made up, silly game in Parks and Rec.
CHARLES MAX_WOOD: Oh, okay. I've seen people actually play homemade versions of it, of that one, I think. But because I went to a gaming convention and anyway, so effectively you have dice and the dice have like little Lego type connectors on them. And then you have the little faces that you can swap out. And so as you play, you build up your dice, and then when you roll the dice, you get more stuff. Anyways, pretty darn cool. So I'm gonna pick that. I think that's about all I've got for that. I am still putting on the workshops. I'm planning JS Remote Conf at this point, and I'm working on getting our first JS Meetup online together. So if you're interested in any of that stuff. Go to topendevs.com and you can check that out. And I think that's pretty much it for me. So we'll go ahead and wrap it here until next time, folks. Max out.
DAN_SHAPPIR: Goodbye.
AJ_ONEAL: Adios.
Bandwidth for this segment is PDAN_SHAPPIR: rovided by Cashfly, the world's fastest CDN. Deliver your content fast with Cashfly. Visit c-a-c-h-e-f-l-y.com to learn more.
React Component and State Management - JSJ 526
0:00
Playback Speed: