307

December 7th, 2020 × #react#hooks#javascript

Hasty Treat - Why should I use React Hooks?

Wes and Scott discuss why they prefer React hooks over class components - hooks allow decoupling state from components, reduce duplication, improve ref handling and more.

or
Topic 0 00:00

Transcript

Scott Tolinski

key. Welcome to Syntax. In this hasty treat, we are going to be talking all about React Hooks And why you might want to use them versus class components.

Topic 1 00:27

Scott introduces the topic of React Hooks

Scott Tolinski

What are the benefits over class components? And, really, what is the incentive to switch To function components versus class components. My name is Scott Talinski. I'm a developer from Denver, Colorado, and with me, as always, is the West Boss.

Wes Bos

Hey. I'm excited about this one. We got a, actually, a potluck question that says, what is the incentive to switch to React hooks versus classes? So we thought we'd turn that into a little episode and explain

Scott Tolinski

why we like them and and why they were were even made. Yes. Yes. And a side note, a meta note. This This is gonna be funny for anybody who's maybe seen this tweet, but I'm broadcasting live from Hamilton, Ontario, and I believe West is in Denver, Colorado Because what we did is we took photos of our background or screenshots of our backgrounds and then swapped them, and we're using them as Zoom backgrounds. So I have Wes's typical background at Wes. The funniest thing to me about Wes using my background is that he has, like, a photo of my son behind him, and, like, that's very funny to me. CSX. I'm, like, cracking up about this.

Topic 2 01:00

Scott mentions broadcasting from different locations using fake backgrounds

Scott Tolinski

So this episode is sponsored by Century at century.i0.

Sponsor spot for Sentry error tracking

Scott Tolinski

It is one of the coolest services that Wes and I have both used for a long time. This service allows you to capture all of your errors and exceptions and see them in a nice table, And you can use the coupon code tasty treat, all lowercase, all one word, to get 2 months for free. This is such a, an amazing service that gets better all the time. You know what? It's it's kind of interesting. I just logged into Sentry just now, and I feel like every time I pop up in Sentry, there's little subtle UI tweaks or improvements here and there. You know, when you think of products that come out and then stagnant, I never think of Century because it's always adding neat stuff. For instance, one of the cool things I just noticing just now, Besides the fact that they got new icons for, React yeah. It looks like the icon for React is different now, but it started adding unhandled tags to errors that I'm having on the site that have been unhandled.

Scott Tolinski

And that's kind of interesting to me because here's a handled error, which is invalid credentials, which is It's one of those things I gotta I gotta change now because my my new account system throws whenever somebody tries to log in with the wrong password. Like, I don't I don't want that. I want The UI to take care of it correctly. Either way, that's a handled exception. However, here's another one. Video JS is not defined, which is probably a race condition due to How we are loading Video JS, and it's not really hitting a lot of people, but it is, in fact, unhandled.

Scott Tolinski

So, that's something you're gonna take a look at and figure out exactly what's going on there. I think that little label they just added really, really helps. So this is Sentry at Sentry dot I o. Again, It's a service that's constantly adding new features, so check it out. Coupon code tasty treat, all lowercase, all all one word. Alright.

Topic 4 03:12

Getting into the topic of React Hooks

Scott Tolinski

React Hooks.

Scott Tolinski

It's funny because it feels like React Hooks came out forever ago at this point to me. But I was thinking about it. It's like the last time we maybe recorded an episode about, Maybe not necessarily about React Hooks, but when we did our our intro to React Hooks, I was just thinking about how we talked a lot about how the future will Tell a lot about how hooks will change our workflows. And now we're kind of living in that future because I, personally, I feel very comfortable writing React Hooks, And I feel maybe even differently about how I use them, when to use them, or the things that I do with them. So I'm excited to talk a lot about Them versus class components in 2021 and how this has sort of changed.

Scott Tolinski

So I think the biggest thing with for me about React Hooks is that they decouple the UI from the logic, meaning that you can take your logic and your things that you're you need to do in your site, the stuff that you need to do. You can take it with you from component to component just like you used to take UI from component to component to component. It's it's almost like building blocks or LEGO blocks for functionality

Wes Bos

rather than building block or LEGO blocks for UI, so to say. Yeah. I think that's, like, The biggest one for me is being able to decouple state management side effects,

Topic 5 04:19

Hooks allow decoupling state from components

Scott Tolinski

things like that from the actual component itself. Can you define side effects For the audience, real quick, that's when I think that is a mysterious word for some people.

Wes Bos

Yes. Side effect is when you're Specifically in RAP, but it it this can apply to all of JavaScript is when your component needs to reach outside of its scope of duty And and do something like, maybe it would update the title tag on a website, or maybe it would subscribe to a database for WebSocket, may events like that. So whenever you need to sort of, like, reach outside. And, also, the the effect hook in in React is also another good way to Rerun any code that you need when you're maybe, like, you're you're waiting for something to change. If you wanna, like, watch for a variable to change, You can use the useEffect Hooked for that. Yeah.

Scott Tolinski

Yeah. And and to me, the improvements that you get out of that is It's purely a just a improvement in quality of life, I think, in working with these things. It makes the code a little bit easier to to understand, to function, to move around, to share, but you also get, like, hands on the code that might not otherwise be there. For instance, like, think about Rehooks in the shareability there. There's a GitHub repo called Rehooks that is a bunch of already made React Hooks that you can just drop into your projects. Right? And that kind of stuff couldn't have really existed besides being in gist and copying and pasting or maybe it ends up being a component or a higher order wrapper component that Just as really, to me, it doesn't feel the same in terms of how easy it is to just throw a function in a ref on here. One of the neat things that I I have noted here is that it makes things like GraphQL Codegen possible. If you don't know about GraphQL Codegen, you basically pass it in the schema, and it cooks out all of your React hooks for you, Including, like, typed React hooks. So now instead of importing a query and importing a useQuery hook and passing that query into there, What I get is a use tutorials query, which is a specifically already made React hook that is completely typed to what I need, and I can just pop that in and spit out the tutorials. And the same thing with any of my mutations or whatever, but I just can't imagine any of that would have been possible without React Hooks. I guess you could do the higher order components, but it doesn't feel the same way to me.

Wes Bos

Yeah. Like, all of this stuff could be done Yeah. Previously with the higher order component like Scott said, but It was really tricky before hooks to take if you had, like, maybe 3 different pieces of state and you had 2 different pieces of functionality and needed to inject all of those things into a component, the way to do it was either stuff it all into 1 component or use it all as high order component, and you'd have to use this like a render Prop or pass it in via props or something like that, and that got a little bit hairy when you had multiple things. So it's really nice with the hooks Could because you can if you have 3 pieces of state, you don't necessarily have to stick it all in in 1 component. You can stick it in 3 different hooks, and they all manage their own nice Tidy, you just sweep everything into 1 Yes. Nice little hook, and then you have 2 little pieces of functionality, and maybe you have Other hooks for that, and you can pull all 5 things in just at the top of your function. You don't necessarily have to do this weird. Just from a syntax Perspective alone, that has been key for me in not having to write these really weird render prop functions because CSF. Render props are awesome when we got them, but the syntax sucks. Sucks to have to write them, and that's just the limitation of of React at the time. Yeah. And right along with that, I think about

Topic 6 06:46

Hooks enable code reuse across projects

Scott Tolinski

state management for me, and not just talking about useState, got a lot nicer, Specifically around other libraries. So there's there's now been sort of a state renaissance in React with hooks because A lot of things have started working a lot nicer. I think even, like, context. Context is one of those things that I used, but I almost kind of used begrudgingly in the past. But with hooks, You just wrap a provider, and then you have your output of the context into its own hook. So, like, for instance, I have a, like, a a used user hook, Which is basically just the output of a a used context with the context passed in there. So now anytime I wanna get my current user, I just say Const user is equal to use user. Now I have the user data anytime I want it, and it's really easy. How many lines of code did a render prop take to do that? I mean, way too much. Right? And now we actually have access to the user in the body of the function rather than just in the UI part of it. So, that to me is a is a big deal. I think about that all the time, just how better my they got. And it also opened the door to libraries like Zustan, which is, like, a super minimal state library where you can pass state around outside of your React. And they they did another one called Jotai. Have you seen Jotai?

Topic 7 08:01

Hooks improve state management with libraries like Zustand

Wes Bos

No.

Wes Bos

What's Jotai?

Scott Tolinski

Jotai, which is a Japanese J o TIE? Jotai is a Japanese word that means state in Japanese.

Scott Tolinski

It's by the same team behind React, Spring and Zoosdend. And so Zoosdend, you could think of it as, like, an easy way to quickly create, Like a use reducer that's outside of any sort of component where Jyoti is sort of trying to compete with recoil Where you think of recoil as being the state itself is like an atom, and you can have, many versions of that specific atom, so you could have many versions of the state. So Jyotai is basically the The Zusdand version of Recoil.

Scott Tolinski

And I I like it a little bit better, and I I really like Zusdand and those kind of libraries that just makes working with state very easy.

Scott Tolinski

So, like, to me, I'm using Zoosdand as sort of like a Redux or replacement, and I'm using I'm not using Jotai yet, but, I think it looks pretty neat. I don't really have necessarily the use case for it. But And to me, state got a lot nicer. That's j o t a I Yeah. For everyone listening and trying to Google it. I had to get Scott to send me the link. Yes. Yeah. Not everybody, took Japanese in college like me.

Wes Bos

Nope. Nope. No. Not everyone did. Nope.

Scott Tolinski

Next step, a big reason is besides being able to to reuse functionality of code throughout your own project and others would be the reduction in code overall. And this is something that I don't know if people think about too much, but with useEffect specifically and, I suppose, use layout effect, we used to have to with the life cycle methods, There was this inherent duplication that could happen between the update and the mount life cycle hooks. So you would have Several life cycle hooks, and many of the times those life cycle hooks were, like, doing the exact same thing. You were having to check a lot of things, but there was a lot of Code duplication that existed in those life cycle methods. And now they can all be reproduced essentially in one tiny little encapsulation, which would be a Use effect, which is targeted to specific dependencies, as in, hey. When this thing changes, rerun these things. Instead of when the component changes Here, just just run a function. Hey. The component changes, just run a function. Now it gets to be, if this thing changed, then do this specific action, And that has led to a a big decrease in duplication of code.

Topic 8 11:35

Hooks reduce code duplication from class components

Wes Bos

One kinda interesting thing that, I was working, I don't know, like, a week or 2 ago, just on moving a lot of the syntax code base over to, be all hooks based. And there's actually quite a bit of state in the syntax website because there's, like, Episode that you're reading, episode that you're watching, where you are playing, pausing, what what is currently streaming, all of that information. And it It was funny. Like, I just deleted a whole bunch of both duplicate code, stuff that needed to happen on mount as well as update, But, also, I had, like, a bunch of custom methods that were simple set staters, like when someone pauses it, set the state. And those all got deleted because this update method that you get from use state was enough just to use that directly, and there was no in between function because previously with state, you had to, like, only update part of it, and now you can just have separate use state hooks For that specific one. So I thought I was I was like, man, this is a really big component, and it probably reduced the code size to about half.

Scott Tolinski

Yeah. Yeah. The the reduction code for me has been big, and it's not just like removing syntactical sugar. It's removing, like, Legit duplication of things that you were having to do twice both on update and mount, even where where some of the other the hooks in the past should component update and stuff like that. I I mean, it just it it reduces so much complexity, and it boils it down into a if thing changed, then do this. You know?

Wes Bos

The other thing was when component did update and you only wanted to run some code when part of state updated, Then you had to, like, say if you'd have a whole bunch of if statements in there your your update one that were just, like, unrelated to each other.

Wes Bos

And with a fact Now you can just just pass the thing that you wanna watch into the 2nd argument of useEffect, and it watches

Scott Tolinski

that value. And if it changes, it will rerun the code. That was a big one for me as well. And not to say I don't have gripes about useEffect because I think the name is not not great, but we can talk more about that at the end. I I do think, for the most part, it's made my code just an insanely amount easier to read. So I don't I don't know about your code base, but I only have one component in my entire level of tutorials out of, like, hundreds of components that is still a class component, and it's because it was like A React YouTube video player that I just copied from an a third party library, and I really don't wanna refactor it because this thing is, like, this thing is big. And this is It's like I didn't write this code to begin, so it's not my style, 1. And 2, it's like, I just I just don't wanna touch it. YouTube isn't a big part of our platform anymore, so it's like, Well, I'm just gonna let this thing be. So I've I've converted my entire code base over. They say not to do that, but it really made me understand hooks a lot better. And maybe if you have a little bit Your time taking that time to convert a bunch of your code to hooks might make you understand the use cases a little bit better, and I think that's a perfect way to see why it's Why the code looks nicer.

Wes Bos

Yeah. I've been I've been just going over mine. Every single time I need to work on a component, that's when I decide to convert it over. And then anything that thing touches, maybe I'll do a few more, but I still have quite a few class components in my thing just because it's not worth it to touch, especially, like Sometimes fussing with it will break it, and you don't necessarily get all the edge cases and and whatnot. So, for me, it's just 1 by 1 as as I need to refactor them in because, like which I also say, and this might be clear, that, like, classes aren't aren't going anywhere.

Topic 9 14:33

Entire codebase converted to hooks except one complex component

Scott Tolinski

I just much prefer to write everything in a function. You know what? I do too, but it's very funny. The other day, Tom, who's a Tom Tom is a developer for LevelUp He was working on refactoring some stuff that we had for our subscriptions code, and he's like, yeah. I threw all of this stuff into a class in all these class methods, And I was thinking, oh, that's very not how I would have done it. But then I was reading how the code actually is to work with, And it's actually very nice because the Braintree API is just about as backwards as you can imagine. And so instead of doing a whole bunch of runarounds in the Braintree API, we now get to call, like, f. Level up Braintree dot cancel cancel subscription. I'm like, oh, that's very nice. That's very explicit what it's doing. I I actually kinda dig classes in that way. I'm mostly functional myself, so seeing classes used in this in this sort of normal way of object oriented programming is not really my specialty.

Scott Tolinski

But no. I I think, yeah, classes definitely aren't going anywhere, but class as React components, yeah, they're going somewhere, so I would get on board with the hooks train. So simplicity and usage is a big thing for me. For instance, like, even just throughout use state or whatever, thing and then update or set thing. Right? Thing, Set thing. That to me is so much easier than set state. Then they have an object. You don't necessarily know what's in that object, but you're gonna set something in that object. This to me is way more simplistic and way more explicit in the code. The code just is easier to read. But, also, one big thing is refs. Right? Refs have gone through so many usages from the initial way where we had them as, like, string refs where you just had, like, a magic string that all of a sudden became a ref. Then there was the whole function thing where you had to set this dot thing is equal to, you know, ref whatever. Oh my gosh. That is such a nightmare. Yeah. Like, the Function wraps? Oh my gosh. I've already forgotten how to do it. I parsed it from I I pushed out of my brain because I don't wanna ever think about it again. It was just such a A tremendous amount of waste of space in my code to do such a minimal thing. But now you get use ref, and it spits you out of ref. You Drop that ref onto a component. Boom. You have a DOM reference at ref dot current or thing dot current.

Topic 10 17:12

Refs are simpler with hooks compared to class components

Wes Bos

Either way, refs make way more sense with React Hooks, And I I do use them quite a bit. So, yeah, this is one of those ones to me that it became it went from being obnoxious and unnecessary to, oh, yeah. This this makes perfect sense. Yeah. I definitely think that they are they're a little harder to first learn, but There's a learning curve. It's it's definitely worth it because, once you get it, Yeah. It's it's much easier, which is really cool. And the the other kind of thing that I I was, like, sort of celebrating the other day is I stopped using, like, variable functions where you're, like, const my thing equals arrow function implicit return. I stopped using that entirely, and that that's Kind of related to hooks because you can only use a hook in a proper function, and and you can export it. And the other thing about that is, like, Even if it's a tiny little component, I I don't like using I don't like using the implicit return for it just because of the Frustration with debugging. You can't put a console log in there, but you can use this little or trick and whatnot. So I've completely I'm curious what you've you've done. I've Completely moved over just using the word function and exporting it,

Topic 11 18:18

Now using named function components instead of arrow functions

Scott Tolinski

if I need to. Yeah. I do the same thing. I I use named Functions.

Scott Tolinski

Function.

Wes Bos

Yeah. That's that's what I do. Yeah. That's good. Yeah. It's it's funny. Like, we I think we had a bit of a moment there with the implicit return, and you Saw people do it for everything Yeah. To to a point where I would I get people emailing me all the time being like, why did you not use the New way.

Wes Bos

The e s six way. The implicit like, it's it's what we're talking about is, yeah, variable equals Parentheses arrow, and then you implicitly return, like, a div or something and put everything in there. And you can't use hooks inside of those, and, also, they're they're very hard to debug. So It's not official. Like, you're not bad if you're doing that, but I personally don't use those anymore, which I really like. Do you wanna know another thing I don't use anymore? What? Default exports.

Scott Tolinski

Don't use them anymore. Oh, you're using everything named? Everything named. In that way, you What about a a page in Next. Js? I don't, have a Next. Js application that I maintain.

Scott Tolinski

So There you go. There.

Wes Bos

Yeah.

Wes Bos

And why? Because of

Scott Tolinski

What? Because they're explicit is really what it comes down to. But I've gone through a bit of a metamorphosis.

Scott Tolinski

I one of the chrysalis or whatever it's Call that became a butterfly, and now I I really understand the benefit of having things be explicitly imported and exported.

Scott Tolinski

The like, automatic imports are easier. Even Just like import helping is easier in general.

Scott Tolinski

Also, there isn't I end up having some situations where I would have The actual component's name be refactored or something in 1 component and not in another, where, like, if I were to change the name of a component, That wouldn't break things because it's a default export, and you're essentially renaming it on import. Yeah. So things kind of got were easier to get out of sync that way. This way, it you don't even have to think about it. If something changes the name, then the name's changed everywhere, and that's just how it is. Or because it's it's explicit. Yeah. Unless you were to

Wes Bos

even if you were to rename it on import Right. The the way you typed it in the file would still be updated, which is pretty cool. Yeah. Yeah. And as we move the entire code base to TypeScript

Scott Tolinski

and all that stuff, becoming more explicit with everything has become one of those things where I've gone from liking a little bit of magic there to liking less magic, and I guess this may be a a transformation. I know it's I do still like some see the magic, Scott, I still like some magic here and there, but I do I I really greatly benefit or understand the benefits to explicit Typing explicit everything and Yeah. Taking a little bit of extra time in the long run helps you out. I think it also has to do with the size of our code base. As the code base has grown, People always say that, you know, some of these issues will become more apparent when your code base grows. And that's really true because as our code base has grown, it it becomes harder and harder to keep track of everything.

Scott Tolinski

Last Last thing I wanted to touch on is if you had any gripes about hooks. I have just some gripes about the naming of, like, use layout effect.

Topic 12 21:05

As codebase grows, explicit naming helps avoid issues

Scott Tolinski

Come on. Like, there couldn't have been, like, used dom effect or something something to explain, like, what it actually is or even, like, useEffect itself. Like, useEffect to me It's not a great name. It doesn't really say what it does.

Topic 13 21:14

Some gripes about hook naming - useLayoutEffect, useEffect

Scott Tolinski

I feel like it could have been named something different, but they had to stick to the use like, maybe Use on changers. I have no idea. I guess that's that's a JavaScript thing. Naming things is difficult. It's very difficult.

Scott Tolinski

Even having the the cleanup function essentially just be the return function of a useEffect, that to me is completely bonkers. And, like, you would have to, Like, know that kind of arbitrarily just exists for you to actually know that. You couldn't look at the code without knowing React and have any clue what that's doing.

Scott Tolinski

So for me, like, the naming around some of these things could have been a lot nicer, and I think that is what led to a little bit of the, confusion and doubts when people try to learn these things is they're they're explicitly not as explicit as on component did mount or something like that. And that to me is something I think could have been done better, but that's really my only gripe with hooks is is naming. And that's at the end of the day, that's just a A matter of learning them. And once you once you got it, you got it. There's a couple things that bug me. Specifically, set interval and set timeouts

Topic 14 22:29

setTimeout/setInterval should be built into React Hooks

Wes Bos

are so difficult, and there are, like, really good hooks out there. I just don't understand why they don't come with React. Like, they're not you have to npm install them, and it's really frustrating. Especially, like, for me, I'm someone who just throws together lots of really quick examples.

Wes Bos

And whenever I hit Something that is built into the JavaScript language, set interval, and set time out, and it's so hard to use in React Hooks.

Wes Bos

I wish that they would make that, like, a first class support and make it really easy to use. Mhmm. And then the second thing I have here is just if you have an async useEffect function, like, Like, do you wanna use a seek await inside of useEffect to fetch data? Because that's a very popular thing to do. You have to either switch to promise based then syntax, or you have to have a secondary function inside of your useEffect function, which gets really hairy really quickly. So I've just switched to using .then and and .catch instead of, marking my thing as a sync. I I bet they could fix that. Have you seen the,

Scott Tolinski

The Vue composition API? No. I have a tweet from Evan Yu who did this. I mean, who did who did this? Who did Vue? The the, creator of Vue.

Topic 15 23:32

Vue Composition API gets naming like watchEffect better

Scott Tolinski

They got it right in my opinion. Instead of calling it useEffect, they called it watchEffect, which to me really describes a lot more. But, also, the return is named on cleanup, so you know it's an on cleanup.

Scott Tolinski

So so those are 2 things right off the bat that they got naming correct in all of this where you can Quickly see, watchEffect and on cleanup, and that's just how it it should work. So to me, like, I I feel like they got they got some of the naming right in a way that,

Wes Bos

the React team probably could have done a better job with, I think. Alright. I think that's it. So, hopefully, that answers the question from secret agent. What's the incentive to switch to Rhyatt Cooks versus Glasses? It's kind of a nice little, like, where are they now? Because, again, like Scott said at the top of the episode, we haven't done a specific hooks episode since they were new. And now that we've been coding them for, like, what, a year and a half now, I think we get them, and we we can talk about how we've used them. Yeah. Sorry. 1 to go back to the Evan You thing real quick, I forgot to mention that the reason why I brought that up in the 1st place was because You can use async directly in the view version of their watch effect. You don't have to you don't have to have a function that calls another function. If you wanted to do And await data fetching, you can do it right in the watch effect, which is really how it should be. Alright. That's it for today, and thank you so much for tuning in. We will catch you on Monday. Nope. On Wednesday.

Scott Tolinski

Peace.

Scott Tolinski

Peace.

Scott Tolinski

Head on over to syntax.fm for a full archive of all of our shows, and don't forget

Share

Play / pause the audio
Minimize / expand the player
Mute / unmute the audio
Seek backward 30 seconds
Seek forward 30 seconds
Increase playback rate
Decrease playback rate
Show / hide this window