about 5 years ago Syntax Podcast
React + TypeScript
- 00:17 Introduction of today's topics: Using React with TypeScript
- 00:52 Sponsored by FreshBooks, Sentry, and Linode
- 02:55 React and TypeScript integration is polished now
- 04:56 Typing basic function components in TypeScript
- 18:35 Typing React component state in TypeScript
- 22:25 Typing side effects with React useEffect hook
Typing basic function components in TypeScript
Guest 2
Rid So I for very basic components that are just JSX element, I let that be inferred. What about you? Yeah. I typically do, I think, as well. There rid Has been some benefit to having it be typed. Some of our components ripped. Cheat sheet, and it was in a issue linked in the the cheat sheet there. And they're basically saying when you use
Guest 1
you cannot type those individual destructured Much prefer to just type them the line before the function. Just create the type. If if you're using them in more than 1 place, then, absolutely, People generally
Guest 1
You're just gonna kinda take a look. Okay. How do I do this? Alright. Okay. Makes sense. Next. Like, it's not like, oh, this is a totally different way. It's it's very much in the vein of This is how TypeScript works. Totally. Which makes sense because it is TypeScript.
Guest 1
rid A number of different ways to type a component in in JavaScript, and I primarily just stick to when you are writing your components, do you typically have a return type in yours? I think and and this rid. This might change. Like, we might have a a show 6 months a year from now. But for something as simple as that, I let
Guest 2
In its own thing, type of props, and then my props are colon type of props. And that's worked out well for me For the most part, but that's typically how all of our our props are defined for individual components.
Guest 1
helps a lot of things because now we have all these babble plug ins where it just rid. Sometimes assumes that you have JSX in your JS files, and you have to run that through it first to convert to, what, create class, something like that. Yeah. It's interesting. I don't know why I ever felt The other day, I had to type something as unknown
Guest 2
as props, I'm interested in knowing what your Strategy is so if we're getting into typing components as props, you can think about components themselves are just functions. Right? And functions have parameters. They have arguments, Of course, that's not going to necessarily work with
Guest 1
When I think in the early days of React, people started using dot JSX what are all these pieces with all the curly brackets and colons and equal signs? Sick.
Guest 1
Structure those properties into their own top level variables with that's why you see the curly brackets when someone defines a function. And
Guest 2
A optional prop that's a type of string, and you have a default value of it. So on that destructure,
Guest 1
in that. So you have to basically destructure,
Guest 2
Ones that don't have any sort of default values,
Guest 1
and you can type those as JSX dot element.
Guest 2
I don't even know what the benefits are, to be honest. But, before, I thought it was clean. I didn't wanna have to rename a bunch of my files or something. I don't know. Yeah. It's funny because I was kind of against it. And I think initially, APIs from a useEffect
Guest 1
in Canada at least, our taxes are done, Thankfully, I just got pushed back a little bit. Last year, ours got pushed, and they just kept getting pushed and pushed and pushed. Mhmm. And this year, Related, but whenever we did the show on nothing,
Guest 2
fresh nondefault data. I don't know. This is not great, but, what it is is a transition into FreshBooks, which is one of our sponsors for this episode. Wes, do you wanna talk a little bit about FreshBooks? I know even though it's June now, technically, it's kind of like tax time. Right?
Guest 1
Send,
Guest 2
Therefore, it's not going to fire an error if you pass children into a component that cannot accept children.
Guest 2
The generic type of FC or function component, which by the way are the exact same thing, one is the shorthand.
Guest 2
Things like as well as the return. So like children automatically becomes typed. Right? But the argument against that is, you know what?
Guest 1
argument or the sorry, the entire parameter
Guest 2
file. Yeah. And using the dot JS for that extension really doesn't have a lot of benefits.
Guest 1
it normally would if you're using a class based component. And then you can go ahead and type what you expect the state of that component and the props of that incoming, thrown in there as well Then you can set some default values there, and it will infer that it is a
Guest 2
So that's that's gonna work for default props, but not if your props have some When you're typing your components you're setting a default value.
Guest 1
items React components,
Guest 1
having known this for 1 minute, rid. I think maybe my rule would be that if it's the built in types, string, number, Boolean, it would be fine. Yeah. And then, obviously, anything anything any custom rid types. I don't think you would be able to Exactly. Do that. I don't know if I would recommend it for most most situations.
Guest 1
In most cases, you probably don't want to use that, but It can be really handy in a lot of little map, whatever, quick little use cases. It's so handy to be able to do that. Totally.
Guest 2
use I don't regret that because rid It's not like I'm doing it still, but, like, I don't know if I would do that again. I think I'm firmly in the camp of, you know, a dot to JSX or a dot TSX file indicates that it is a JSX Next step is going to be useEffect,
Guest 1
re You can export them or throw them in a separate file and import them if you need them. But, generally, yeah, I'm I'm doing the same thing as you. It's just typing them right before And if you ever have a useEffect
Guest 2
I think that makes sense. Yeah. That's funny. Yeah.
Guest 2
No. But it is an option in your tool belt if you Want it. Yeah. It's kinda like the, one liner implicit return, no parentheses.
Guest 1
default parameter values, or anything like that. So that can happen. And and for very simple components, sometimes, like, That is enough. That's more than enough, and and that's all you need. And other times didn't know that. It can be a little tough. Yeah. I didn't actually didn't know that at all. That's kinda cool. Because so that is a perfect use case for if you have, like, I've got a little example in the notes when rid Scott and I are talking right here. We have a joke, and the joke has the text of the joke, and it has an ID, and it has a status. So it's string string number. And instead of having to type out that it's string string number or if you're just passing, like, an ID reminders for those people that need need the invoice sent to them, and they, oh, I forgot to pay it. FreshBooks will do all of that for you,
Guest 2
Yes. Let's say you have a prop, and it would be like name. Name is equal to and then quotes Scott in that, not something that I thought I would say when I first started looking at TypeScript and React. That was one of the rid. The 1st barriers to entry was just how many extra characters it was to do certain things, and once you get over the clutteredness of some of that, it does read pretty well you train your eyes to it.
Guest 2
in that destructuring.
Guest 2
And then I define the prop types there, and then I will in the either destructuring or when you use props, I usually just destructure the props out. You give it a value or you give it a type just like you would any other parameter. So I typically create my types outside of the function found a pretty convincing argument for why it's should be discouraged to use that, but one of the benefits of that is you do automatically get
Guest 1
Yeah. I'm I'm on the same page as well. So just to be clear,
Guest 2
So, like, if if if you have Sometimes, they can be a little bit more complex whether they have an object, maybe an array of stuff. Maybe you just need some very specific types of values in there. You have some types to find elsewhere,
Guest 1
React, you had the props, rid. You had the default props. You had the type of the props.
Guest 2
Besides, At least best practices or good explanations for everything that we're talking about in here. This repo is really the the place to find it. And Once this thing came out, I know Swix was a part of it. I don't know. Did he author the whole thing? Or no. I think there's there's a a bunch of devs behind it. There's a bunch of devs behind it now, but I think he might have created it initially. Oh, yeah. But, yeah, it's it's, And you can type those the exact same way you would typically. So you could potentially create a type
Guest 1
and start thinking what you're gonna do with all that extra time you're saving. Thanks so much to FreshBooks for sponsoring.
Guest 1
Yeah. Well,
Guest 1
is a crowd favorite for cloud accounting. It has an intuitive dashboard rid. Easily navigate over. You can log all your expenses. You can see all of your
Guest 1
generic,
Guest 1
like, joke, age, counter, gotchas here or there or, like, rid The useEffect function cannot be asynchronous.
Guest 1
outstanding invoices, who you've invoiced, when you invoice them, automatic jsx dot, and then there's a whole bunch of different elements on there. And the the most basic one is dot element, capital e. Yeah. What do you think about the JSX And inside the useEffect, you'll know that you can't use an await keyword
Guest 1
your props, and your state just like,
Guest 2
outside of the f c function component, fantastic repo
Guest 2
That's a little tidbit for you. I always just use FC
Guest 2
The actual function, just for my own sanity stake. Yeah. Did you know that the default props can be inferred?
Guest 1
React, if you already know TypeScript,
Guest 1
Put that on ice for a second. I'll I'll I'll ask you what you think of that.
Guest 1
so you are just on your taxes. Now this is the year. This is your year. You need to start fresh. Switch to FreshBooks and join over 24,000,000 you use a dot t s x file. And when you write regular TypeScript, you use a dot ts file, and those are completely separate, which is funny because
Guest 2
and dot TSX files? I like it. I like that it's explicit now that it's JSX or TSX, and I,
Guest 1
So React, when you're when you write React code in TypeScript,
Guest 2
of, you know, type of props. I usually if I'm actually typing my props, I usually do type capital p props is equal to, and then the props, In reality, with TypeScript in state in React, unless you're getting into use reducer or even context is pretty simple if you know what you're doing, Once you get into,
Guest 1
rid Regular old components, the the word function, the name of the components, parentheses,
Guest 2
Giving it an explicit return of JSX dot element, but I haven't used it really myself,
Guest 1
and some text to something, How are you doing today, mister Scott Talinski? Hey.
Guest 1
generic. Rid So what's the argument against using that then that you're saying you found a pretty good argument? So this argument was found on the When you destructure re FreshBooks. Hey. Hey. So FreshBooks Good stuff. Let's get into it. TypeScript and React, and I was like, this has gotta be wrong. Basically, you're forcing it into unknown and then rid back into the type that you want it just to get the TypeScript compiler.
Guest 1
generally, people don't just pass the props object And then access props dot age, props dot counter, props dot fetch another joke.
Guest 1
Individually,
Guest 1
rid Syntax and enter syntax in the how did you hear about a section which is I think it takes in 2 arguments. The the first one being the function that runs and the second one being the the list of dependencies, arguments,
Guest 2
So okay.
Guest 1
Often, people would create the type for the props in line, and then you'd also have the return type. And especially to somebody who's new, you kinda look at that and go,
Guest 1
in your function definition, you have to automatically be ridged, and you'll have access to all the properties when you start to go ahead and use that state
Guest 1
they're pretty simple. At the the very highest level is that you you take in props. We'll talk about typing props in just a second. And then from that, you return some JSX, And then it returns the cleanup function if you do return something.
Guest 2
that that was cool to use a, you know, JSX in a JS file, but I did. That's fine. Do you typically Explicitly,
Guest 2
The return type of JSX element so that if you're not return you know, you ever get those errors in your code that's like You're trying to load a component that's not a function or that's not a a component. You're you know, might be whether that's an object or whatever that error is. I I'm I'm I don't know the error offhand, but I've seen it at time to time. Basically, when you're trying to use something as a component that's not a component, I found this can help with that,
Guest 2
the React FC or React function component, which
Guest 1
all the props that you wanna take in, and then The returned value from that. So for that type, what do you what do you even call that? Just a function component, I guess? Rid Yeah. I'd say so. That's all I do. They used to be called stateless functional components. Now they got state. Yeah. Then we got hooks, and now they got states. So now they're just rid. Functions that return some some JSX. Now they're just components in my mind. Yes. If you make a component, that's, like, the base way to go ahead and do it, And as the type name,
Guest 1
Incoming props are going to be it's pretty pretty straightforward. Like, a lot of the stuff in
Guest 2
Every component that you make will automatically have a children prop regardless if it's used or regardless if it's accurate.
Guest 2
It may be one of those things to be a little bit cognizant of rather than, you know, maybe dictating your life over it. Although, you know, I've never hit this bug myself, but it does seem like a pretty good reason to not use it unless you know what you're doing. If you are using class based components, there is a,
Guest 1
people who use it and love it. It's super easy to get up and running with award winning support. You are never alone. I can attest rid That I've called support a couple times. Try FreshBooks for free for 30 days. No credit card required. Go to freshbooks.com/
React and TypeScript integration is polished now
Guest 2
is really one of the best experiences Rid. TypeScript can infer without you having to explicitly type it that that type is going to be a string.
Guest 2
in TypeScript for me. Like, it was definitely a wow moment for me
Guest 1
built in browser APIs Mhmm. But doing it in TypeScript.
Guest 1
There are
Guest 1
pretty well typed, but I I do hit little Sick. Know what else is sick? State.
Guest 2
rid Part of your code base anymore or has been changed, and and TypeScript is able to find those bugs
Guest 1
There's some stuff that you get into in TypeScript and and even like, I've been doing a lot of, rid I call it vanilla TypeScript, which people don't really understand. I need a bit of a better name for it, but, like, what I mean by that is Doing a lot of, like, vanilla DOM stuff, so just using
Guest 2
rid to keeping the whole thing in sync by making just changes whenever it came around. Alright. So let's kick it off with components.
Guest 1
And I was like, oh, okay. And I I, like, asked around. I was like, what's the best way to to actually do this properly, and everybody's like, that's kinda the best way. And I I don't feel like I hit a whole lot of Stuff like that in React. So, yeah, it's a it's a good place to be right now, I think. Yeah. And I I actually you know, read. Authoring React code that has been typed You're Typing 3 things, and it's you're creating a new type by putting curly brackets. And then sometimes you also have default parameters
Guest 1
And for the most part, that stuff is pretty well they did not get pushed, which people are all up in arms about. But they wouldn't be up in arms about if they used
Guest 1
writing my React apps in TypeScript. I feel like it is at a point now where it's pretty polished.
Guest 2
when you all of a sudden see a component that you haven't touched in 6 months or something. Like like, this is an old component. You You just kinda open it it up. You're looking at it, and then you see it's underlined in red. And you see it's being passed a slightly different prop or maybe even outdated prop. And re It might not have surfaced as a bug in your code because, hey, this is just an extra prop being passed into this thing, but it's not the, you know, the low rid Chill Lo Fi beats to study 2 on YouTube. Do you ever listen to that YouTube channel? Once or twice, I believe I have, but I I know the vibe you're talking about. Yeah. It's that specific vibe, and that's exactly what's going on over here right now, and I'm liking it. Yeah. Yeah. I could do some of those low five beats right now.
Guest 2
way, way better, I think, than than we were ever able
Typing React component state in TypeScript
Guest 2
use state call. Right? So it's a use state
Guest 1
Mhmm. And those things will, obviously,
Guest 2
And then in parens, the boolean value. If you have a very simple, don't have to do anything. React has useEffect typed correctly, and for the most part, rid have a children prop Mhmm. Or is it appropriate to be used that way? So they're saying if you use f c or function component,
Guest 1
value Yeah. That is already typed, it will infer that type from it. I think I still prefer
Guest 2
Very, very simple, and it reads pretty well in my opinion, which is
Guest 1
So, because something in a function in TypeScript, and a return type, and then we're just like, okay. This is this is very hard to read. So Mhmm.
Guest 1
a bit deeper dive a couple weeks ago. Mhmm. There was I said I said that the
Guest 1
how how do you type state, Scott? So state is actually pretty easy.
Guest 2
Believe it or not, you could actually
Guest 2
have state inferred as well for basic state types. For instance, if your basic state type is rid Like, let's say it's a boolean, is toggled. You have a boolean is toggled. Set is toggled are the 2 props the or the parameters that you're destructuring from the result of your that has really just I mean, if I wanna see
Guest 2
rid. Then you have
Guest 2
inside of your inside of your application. Yeah. It's pretty simple. Rid. To be honest, you look at some of this, so you get your 1st TypeScript error,
Guest 1
And then React will take care of the rest in terms of the function to update your state will be typed automatically for you via that, rid. All through the use of generics. Yeah. That this is a really, really good use case for explaining what generics are Because the function is use state, but you don't wanna create any new function for every single type of state Right. That you would have. So you just pass the type of your state to the angle brackets
Guest 2
you know, the actual process of this using, these generic resolve values, it is
Guest 2
Well, you can actually pass these right along through using the syntax with the angle brackets where you would say use state,
Guest 2
the type is of your state that needs to be applied to the state's value.
Guest 2
TypeScript's gonna know that it's a boolean, and you don't have to do anything extra.
Guest 1
state is rid Super sick.
Guest 1
jokes and set jokes. Basically, you know how how use state returns you an array. The first item is
Guest 1
type can be inferred from a generic, And a couple people asked for an example of that, and I I tweeted out an example just with regular JavaScript. And a couple people said this is, yeah, this is how React does it. So if you pass typing it out just because you can see it without having to hover over the type to see what type it is. But, yeah, it's it's pretty simple. And then from that, you have you are returned
Guest 1
an array With it, which is user and and set user or,
Guest 2
setup like that,
Guest 1
of use state. And then, also, like, when we we did the TypeScript,
Guest 2
the angle brackets and then whatever
Guest 2
and that error has to do with the, you know, the re Type being on that function. And the the type error that comes in that case could always be a little bit confusing, and you say, oh, great. Now I gotta go down this rabbit hole. But
Typing side effects with React useEffect hook
Guest 2
You know what's funny? It's because I write code like this in my tutorials when I'm teaching React. Right? Yeah. I I actually don't write the void yet, but that's a really neat tip. What's funny is that, like, since using Apollo or React Query, I don't know if I've had to call too many children should probably be defined on its own because not every React component
Guest 2
I I've never done really anything special in TypeScript with useEffect was the type of person who was writing JSX in a dot JS file, and I kinda
Guest 1
type, which is a function that return doesn't return anything.
Guest 1
So if you wanna use a promise based function inside of a useEffect,
Guest 1
Not even nothing. It's I want to ignore string in string. I think that TypeScript infer the type from that Just because it's it's less typing. And, also, like, when I initially got into Oh, That's the first time I've ever run into a situation where I needed to use void.
Guest 1
rid Here, let me see what the specific error is. TypeScript ESLint no floating promises is the one that gets me here. Promises must be handled appropriately or rid Mostly marked with a void. So popping a void in front of that, basically, just ignores the promise comes. And a a couple of people tweeted that to us After we did that episode, and I go, Using React with TypeScript. So we're gonna go through
Guest 2
maybe unmount, maybe unmount, those types of things, this is when you use useEffect. Now The cool thing about React and useEffect is, hey. You largely
Guest 1
Since then, isn't that kinda interesting to think about? Those libraries kinda take care of that for me. Yeah. It is it is really nice when a library will do that for you. It's it's true. It's it's only when I'm rid Explicitly running a fetch request and not using a a library like React Query or Apollo, something like that. Yeah. So that that's the little tip there for using VOID. I don't think I've ever seen that or or thought about that. No. Me neither. I was surprised when a couple and, like, it was it was one of those things where rid. 1 person replied to the tweet, and there was, like, a 1,000 likes on it because everyone's like, oh my goodness. That's the best. That's cool. Hey.
Guest 1
and we talked about the void keyword Yes. And we said I think we both said, like, I've never never used the VOIP keyword in my entire career. Oh, I use it in in oh, you mean in JavaScript itself, not in a type? Oh, yes. Yes. Sorry. Correct. The in the actual in in TypeScript, we have avoid the undefined that could be returned from this thing. Right. That's what void does. So there also is a void keyword in a React dot component that takes 2
Guest 1
rid You have to and then colon, and then you have to give it the type rid for all 3 of those things in one go. And that can get a little bit hairy because you're often destructuring 3 things.
Guest 1
so I had to turn off 1 rule you have to type the entire But rid. React gives you a namespace called, Yeah. Because it it just takes in 1 argument, because a lot of the, like, plugins didn't work in For, like, Versus rid in Sublime and yeah. Because it, like, in it, like, detected the what what you're in. But now I think about it. If you're writing rid. Jsx in a dotjs file, that's not really JS. It's JSX. Right. So maybe I'm swinging back to the other end of things now and saying, rid maybe dot t s x. And it it certainly This is not specifically TypeScript Even, like Scott, you said if you use use state and you pass it like a Boolean. But if you pass it any
Guest 2
specifically.
Guest 2
which useEffect is commonly used for life cycle in React. Right? Rid. Side effects, they say. If something needs to run on when something is changed,
Guest 1
I did have to change my ESLint rules to allow void, though, writing The state itself, and the 2nd function is the updater.
Guest 1
because
Guest 1
chain a dot then and a dot catch onto the end. And often, you see people just chaining them on and and doing nothing with them. So if you really don't care about either the results because the result is being put into state or the catching an error, rid. You can pop a void in front of it, and that will ignore the promise that has returned from the get joke, and that will pass any
Guest 1
that needs to fetch some data on mount, Generally, you I have, like, a little function called get joke, and that's that fires off of fetch request. And when the fetch request comes back, it sets the joke to state. Read.
Sponsored by FreshBooks, Sentry, and Linode
Guest 1
Rid They are cloud computing developers trust. They have a Linux servers you can use to run literally anything you want that runs on Linux servers. We'll talk about all of them partway through the file names. Mhmm. And we've sort of gone away from that, And now it's come full circle and that we're using dot TSX files for authoring React.
Guest 2
a it's a rainy Monday morning here, And I'm just, I'm I'm kinda digging the vibe. You know? It's raining here too. Do you ever listen to the,
Guest 2
repo that has,
Guest 2
At least, for the most part, I think, re when I was first started getting into it and first started learning it, I don't know if there was the same level of
Guest 2
I'm doing good. It's
Guest 1
fan. How about you?
Guest 1
Yeah. I I've got the windows open right now, and I just love when here in the rain. Oh, yeah.
Guest 2
resources out there. So some of it was a little bit you'd hit problems in rid I gotta go to Stack Overflow and figure out what's going on. But I do wanna say before we get too deep into this, a lot of these notes are going to be coming from the re
Guest 2
the React and TypeScript cheat sheet. So we'll make this link available to you in the show notes, But this is, just a fantastic,
Guest 2
I'm, I think I'm a pretty big fan. Yeah. I think I'm a pretty big fan.
Guest 2
it's fantastic. So give this thing a look. It's gonna be in the show notes. Definitely well worth your time. Yeah. I have really enjoyed
Introduction of today's topics: Using React with TypeScript
Guest 1
custom hooks, and ESLint, all kinds of good stuff. So we are sponsored by 3 awesome companies. Re 1st one is FreshBooks cloud accounting. 2nd 1 is Sentry
Guest 1
pretty much everything as to, like, how do you set it up and and how do you do components and state and props into passing data, JavaScript.
Guest 1
Ready. Today, we've got a really good show for you. We've been doing a a whole slew of TypeScript shows lately, and this is the show that is entirely on Because
Guest 1
error exception and performance tracking, and the third one is Linode.
Transcript
Announcer
You're listening to Syntax, the podcast with the tastiest web development treats out there. Strap yourself in and get ready. Here is Scott Talinski and Wes Bos. Welcome to syntax, the podcast with the tastiest
Guest 1
TypeScript Interesting.
Guest 1
and React treats.