Check out a free preview of the full TypeScript Fundamentals course:
The "Stateful Components" Lesson is part of the full, TypeScript Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Mike discusses stateful components, which are usually classes that describe props and state. Mike takes questions from students.

Get Unlimited Access Now

Transcript from the "Stateful Components" Lesson

[00:00:00]
>> Mike North: The last thing we did was, we built a stateless functional React component using TypeScript. And the benefit we saw that TypeScript brought to the party was that we were able to use an interface to describe the props object that this component was looking to receive. And we saw that there were a bunch of things where using regular JavaScript, we would get no warnings about, we just rely on our testing or whatever other assurances we have to catch that kind of problem before we shipped it.

[00:00:35] Whereas TypeScript was bringing those errors up to compile time, where we saw that is was unhappy with us until we provided it the data that it had stated was required by way that interface for the prop's object. So where we're going with this is we're gonna talk about a stateful component.

[00:01:02] So stateful components, you'll recognize these as usually, classes, Java Script or TypeScript classes. And you'll see that in this situation, we've got props. So we bring in a prop of name, but this component also has a time state, right? And when the component is mounted, when the components is inserted into the HTML, it generates a new date value.

[00:01:31] And it sets it's state as like, the time property on that state object is set to whatever that data is. And now when we're rendering this component, we use something from props and we use something from state. So we render the isostring from that data object and we render the name from the prop subject.

[00:01:49] You'll note that the React component type definition here, we're not using react.sfc anymore because that is just for stateless functional components. Now we're using this React component type definition and we pass in two generic type parameters there. The first one is props and the second one is state.

[00:02:13] And you see here, like a very common pattern here is to of course begin both interfaces with the letter I for interface so, we that that's not a class for working with. That is just a shape of some data not an implementation. And then adding props and state to these interfaces themselves, so there's no confusion whatsoever in terms of which is which.

[00:02:35] I love this pattern because at least when I was first learning React, I would lose track of what data lives on props and what data lives on state. When you're working in the internals of this component, sometimes it's not immediately obvious what should be passed to you from the outside versus what is your own private data, right?

[00:02:55] And now in this case, because there is some structure around these two objects, it saves us from things like misspellings. Or it points out anytime we've reached to props or when we should have reached to state and vice-versa, because it will say, look, this property is not available there.

[00:03:13] For that reason I also try to make sure that when I design React components with TypeScript, I tend to wanna have these two interfaces for props and state overlap as little as possible. So that you don't end up in a situation where they both have name on them.

[00:03:31] If they both had a name property on each of those interfaces you start to lose some of that clarity between props and state. Whereas if you have none intersecting shapes with completely different property names, it becomes really nice and you can avoid a lot of potential confusion there.

[00:03:54] Especially if you're dealing with highly complex React components, where you weren't the original author, you don't have all of the context of how this was built. Really, really nice to have up front a definition of these are the things that belong to my state, and this is for the props.

[00:04:11] With that, let's look a little deeper into our little demo, the clock demo. Yes.
>> Speaker 2: Could you just maybe elaborate a little bit on how
>> Speaker 2: to implement TypeScript into a project? Like how to get it in to Webpack and Vega kind of the best practices in that way?

[00:04:34]
>> Mike North: Sure, absolutely. Let me just finish this little bit up, and I'll jump right into that topic. So this component here is a clock, it has a color that is passed in from the outside world and it has a time, that's the current date. And you can see that when the components mounts at every 20 milliseconds, it will basically begin pulling every 20 milliseconds in order to refresh its time, right?

[00:05:03] So when we call this .tick, it's going to just set a new state down here. We see we've made that private, no one else can use that function. Another great thing to get added to React components like no one outside of this components definition can refer to take here.

[00:05:21] And in fact if you try to overwrite this property, you'd get a complaint from TypeScript saying, there's something there and you're not allowed to access it. So, in this situation you're gonna end up with some very clear idea of what's available there versus what's available here, color, that's the only thing.

[00:05:45] All right, so that states for components. Now, answer your question about mixing JavaScript and TypeScript together in an asset pipeline, right? How do you end up with like modern JavaScript and TypeScript side by side. So, we looked at yesterday how classes were implemented differently in Babble versus in TypeScript.

[00:06:09] Mainly that Babble has a central definition of a function called create class, and it leans heavily on that in order to define new types. TypeScript does not have that, right? It doesn't have this sense of a polyfill that can be leveraged multiple times across various things, I don't believe it does.

[00:06:33] In any sense, in this specific case, it certainly does not. The consequence is, if you mix TypeScript, like classes that were generated by the TypeScript compiler and classes that were generated by Babble. You can end up with some issues in terms of inheritance chains and supers working the way you'd expect them to work.

[00:06:53] So my advice here is to basically have, if you're using TypeScript and Babble side by side which is not only possible, but they work really, really nicely together. The idea is you want TypeScript to do as little work as possible. Just get it out of the TypesSript world and into as modern a version of JavaScript as you possibly can, and then let Babble take it the rest of the way from there.

[00:07:17] Here's how that would look. So the file that drives this in the root of our project is this tsconfig.json, and this is where we also have the rest of our compiler options. So, we can see that this target property lets us specify the ecmascript target version, and permitted values are all of those things.

[00:07:41] One of the nice things that Visual Studio code adds to this developer experience, is there's even a schema for the way this JSON object is structured. So this is not a plugin I'm about to show you, it's the fact there's some site, I think it's like JSONschemas.org.
>> Mike North: Yep.

[00:08:05]
>> Mike North: So json-schema.org is a place where you can see there are many specifications for package JSON, and various other things.
>> Mike North: Let me make sure that I am looking at the right thing.
>> Mike North: Let me do a quick Google.
>> Mike North: Yep, it is correct. All right, so for example if we were to look at Babble RC is JSON schema.

[00:08:52]
>> Mike North: It looks like this. So we get nice auto-complete right in our editor here. And that's what telling us that those are the valid options here. So we would basically say we want TypeScript to compile us ES2017, meaning it's gonna do things like leaving those JavaScript classes completely in tact.

[00:09:13] It'll leave them intact, it's just gonna do the type definition stuff. It won't even mess with the generator functions. It'll let Babble handle that kind of thing. It'll only take away very TypeScript specific things and leave us with almost no advanced modern JavaScript, having been boiled down into simpler stuff that older browsers can understand.

[00:09:39] And then you would let Babbel take everything from that point the rest of the way. The benefit being now that all of your JavaScript and all of your TypeScript in terms of classes, and generator functions, and things like that, they were all processed by the same tool. And they're all going to work together just as if you had been using Babble alone without TypeScript, does that make sense?

[00:10:03]
>> Speaker 2: Yep, thank you.
>> Mike North: All right.
>> Mike North: And by the way you would also do this, you would say I want to generate ES 6 modules instead of generating common JS modules. We're currently building common JS modules just so that Node and our browser-base code can kinda share that one API keys file.