- One of the hardest parts about developing code
is that as your projects start to grow
and grow in complexity
and you get more and more people on your team,
it becomes impossible to memorize
and know everything about the project you're working on
which means it's incredibly important
that you have good tooling set up to make it easy
for you to able to read the code, see what's going on,
and be able to detect any mistakes that you have.
But if you don't have any type safety set up in your project
it can become incredibly difficult to actually check
for all these different problems and prevent some bugs.
So I wanna look at this code really quickly.
Everything looks like it's working just fine
but we have a glaring bug in the code
that's not actually super apparent to us.
We look at our code here, you can see
that we have a child component which takes a name
and age and then a child inside of it.
And that all looks perfectly fine.
If we go over to our actual code,
everything in here looks perfectly fine.
We're rendering out the name, we're rendering the age out.
Then we're rendering out what their age will be in 10 years
by just adding 10 to their age.
And then we're rendering out the children as well.
Just by looking at the code, everything looks fine,
especially if you just look at one component on its own.
This component looks fine.
There's no errors.
We can ignore these errors up here
for now 'cause that's just related to prop types.
And if we look at this, you can see again there's no errors.
Everything looks perfectly fine
by just reading it and looking at it.
But if we look at the output, obviously something's wrong.
Our name is fine, our age is fine,
but our age in 10 years is slightly different.
I hope I'm not that old in 10 years.
And then down here the children are printing out fine.
So the problem that we're running into
is we have a tight problem.
We are expecting this age that gets passed in
to be a number.
So when we add 10 to it, we expect it to go from 28 to 38.
But the age is actually being passed in as a string here.
So what's happening is we're adding our string 28
and we're putting 10 at the end of it.
And that gives us the string of 2810.
This is obviously a problem
and all of those red squiggly lines that we've seen
up until now that talk about React prop types,
that's to try to prevent this problem inside
of a JavaScript code base.
Now in React there are two main ways
to deal with type safety.
You can do number one
which is going to be doing prop types.
And number two is to use some type of type safe library.
TypeScript is probably the most popular thing
that you can use, but you can use something
like JS Doc as well.
Personally I'm going to be covering TypeScript
in this course because it's currently by far the most
popular and it's the one that I think is the most useful
but you can use whatever you want.
Now in this video though, I am going to be covering
prop types because that is one of the options you have.
I will say though, if you have the option
to use TypeScript 100% of the time, use TypeScript instead.
And the main reason for that is prop types
are a runtime check, which means it checks your types
while your code is running and TypeScript checks your code
before it actually runs, which is a massive benefit.
But I'm gonna be talking about prop types
because they are useful if you can't use TypeScript
or any other typing type of code.
Prop types is like the last resort you can use
to add a little bit of extra safety to your code.
So in order to use prop types in React, what we need to do
is we need to install the prop types library.
So I'm gonna do that real quick.
npm I prop types, and this is a library
that's maintained by React.
So it's you know, going to be great and work all the time.
npm run dev, that's going to be fine.
Now to actually use prop types,
all we need to do is take our component,
(keys clacking)
- And we have a prop types property
that we can define on it.
So we can say prop and then Types
with a capital T set that equal to.
And then here we can actually get our prop types.
And if we come up to the top here and we import prop types
from that prop types library, now we have access
to everything inside of our different prop types.
So I can come down here and I can say like prop types dot,
let's do it outside of here
so I can actually get auto complete.
Prop types dot.
And you can see we have a bunch of different options.
So for example, I can say that we have a number,
we have a string and so on.
If I spell string properly, there we go, string.
So what you need to do inside of here
is just define all your different types.
So what are the props we take in?
We take a name and age and children.
So I can say name is going to be a propTypes.string.
I can do the exact same thing with our age
which is a propTypes.number.
There we go, just like that.
And the really nice thing is you can see immediately
our red squiggly lines are going away
'cause we're actually typing our different props.
And then finally our children here,
this one is going to be propTypes dot.
And we have a few different options you can use here.
Node just means it's something that you can actually
render out, which is what we want in our case.
So we're gonna do that.
But something else that you could do
in this place as well is passing the text element
and that's going to be specifically
for like a React component
and not just something that can be rendered out.
So let's change this back to node
'cause that's what we really care about.
Give that a quick save.
And now you'll notice no errors at all are in my code
and it's because again, prop types only run in runtime.
So they only run when your code is running
and they print out errors to your console.
So if we inspect our page and we go to our console, boom,
we get a warning failed prop type, invalid prop.
Age of type string should be a number.
So it's pretty much telling my age I patched in a string,
it should be a number.
Now if I go ahead into here my app,
and I change this to an actual number,
we'll now notice our code works properly over here
just like we expect.
And if I inspect my page
and I just clear this out and do a refresh,
you'll notice that there are no more errors
which is exactly what we want.
So I was able to detect the error
but only if I was looking at my console.
So it's obviously not ideal because I need to be looking
in the console actively
to find any of these different errors.
And that's the reason again that I prefer to use TypeScript
or some other typing checker as opposed to prop types.
Now by default when you define a prop it's optional.
So for example, if I came in here
and I removed my name property,
you can see if I save, if I inspect my page, not V source,
if I inspect my page, go to the console, we get no errors.
If I wanna make it prop required
I need to need to call dot required
on the end of it, isRequired just like that.
And now if I save and I inspect
you'll notice I now get an error saying
that name was marked as required but it's not passed along.
So you can add different things
to the end here to make them a little bit more specific.
So for example, I can make my string required
by passing along, is it required?
Now I really briefly just want to kind of go through
a bunch of different types that you can check for.
So one type that you can check for is any that's just
saying this can be literally anything at all.
So it doesn't matter if I pass it a string,
if I pass it a number, if I pass it,
you know a Boolean like true false,
it doesn't matter as long as you pass something,
that's fine, that's all that matters.
It's literally just anything at all.
It just has to exist.
We also have the ability to do any other basic types
of like Boolean and so on.
All of those that you're used to
are going to be inside of here.
And then we also have arrays and we have objects.
So if we do object like this
it's just saying it expects us to pass in an object.
But if we do shape of or actually just shape,
that'll allow us to pass in a specific way
we want our object to look like.
So by just doing object, that's just saying
accept literally anything that is an object at all.
But if we say shape inside of here,
we can pass it what we want the shape to be.
So for example, if I change this to like address
and I wanted it to have a street that is a string,
well I could just say propTypes.string, just like that.
And let's just say I wanted it to also have a city
and we'll just give that a propTypes.string.
There we go.
Let's say that I wanna make this required.
Whoops, required.
There we go.
And I also wanna make both of these required.
So isRequired and isRequired.
There we go.
So now I'm obviously going to get a bunch of errors
in my console because I don't have that address property.
So there we go.
Obviously I should pass along my address.
So if I come into here I can say address just like that.
I need to pass it as an object.
So I also know that I need a city and a street.
And you'll notice I do get auto complete
because of these prop types, which is really nice.
So the prop types can at least help you with auto complete,
which is really great.
Let's come in here with the city, we'll just say Hi,
and we'll say street, it's just gonna be Main Street.
There we go.
And now that'll get rid of the errors.
So if we inspect our page, go to the console
you can see we have no errors when we refresh our page
which is what we expect.
So again, shape is for specifically defining what the shape
of your object can be,
and you can make as much nesting as you want.
For example, if I wanted this to be a shape as well,
I could just come in here with a shape
and again nest further inside that.
Now in order to do an array, this is just going to be array
and that's just saying literally anything
that's an array is going to be fine.
And then we have arrayOf, and that essentially
allows to just find what we want our array to look like.
So if I wanted to pass in an array of strings
I would just say propTypes.string.
And that's going to gimme an array.
And the array must be filled with only strings.
Now commonly you may want to have an array
that has multiple types.
Like let's say I wanna have an array
with strings or I want to have numbers.
Well I can use the propTypes.oneOf type
and I could use the oneOf type inside of here.
And now I'm saying I want it to be
either a string or I want it to be an array.
Or actually no, I want it to be a number like that.
Put this inside of an array so I'm passing an array
of those different values to it.
Make sure I get all my parentheses correct,
give this a save.
There we go.
So now I'm essentially saying I have an array
of a specific type and that type is one
of either a string or a number.
The nice thing about these prop types library
is that it reads relatively like English.
So it's a little bit easy to see what's going on.
Now let's say I wanted to have like an enum.
For example, let's say I have a status here
and I wanted it to be either loading or error.
What I can do is I can say propTypes.oneOf
not oneOf type, but oneOf,
and this I can just pass it an array of values.
So I could say like loading and error
and now this status must be one of these.
So if I try to pass along a status
and you see I get auto complete
or actually it doesn't look like
I'm actually getting auto complete on this
which is a little bit annoying, but you can see
if I pass in loading, everything will work fine.
If I inspect my page, go to my console
make sure I get rid of this address prop
which is no longer there, clear this out, refresh.
You see I get no errors.
But if I try to pass along something that's not
one of those statuses,
you can see immediately we get an error
because it's not loading or error.
So it's really great for different status related stuff
that you want to do.
Now the final different type that you can deal with
is the exact type, exact is very similar to shape
except for the way it works is it allows you to pass
in an object that only has these props.
So let's say that we want to have here an object that has
a name which is a propTypes.string, just like that.
And we don't want it to have any other properties.
Actually let's do age as well.
propTypes.number.
There we go.
And we'll just call this obj for object.
So what I can do inside of here, obj,
that's going to be an object.
And this object is going to have a name
which is going to be Kyle.
And we'll do age 28.
So it has all the properties that we expect it to.
Let's get rid of all the other stuff we don't need.
And now if I inspect, go to my console, clear this out,
refresh, you notice we get no errors at all.
Now if I add another property onto here,
let's just, doesn't matter what it is,
just any other property you'll notice we now get an error
because it's saying
that we only expect there to be a name and an age
but we're getting this other random property being added on.
So exact lets you only define
that it has specific keys in it
and it does not allow random other keys.
While if I used shape here instead,
they both work exactly the same
but shape allows me to have extra properties.
For example, now when I refresh this
you'll notice we get no error at all.
And that's because it's saying I just expect it
to have these two properties.
I don't care about any other properties that has,
as long as it has these two properties.
That's all that matters.
And that right there is a really quick overview
of everything you need to know about prop types.
You can go a little bit deeper
if you want by reading through the prop types documentation
but that covers pretty much 95% of your use cases.
And if for some reason you're using class components,
prop types work exactly the same,
you just define them directly on the component.
So it works exactly the same
between class and function components.
Now in the next couple videos I'm gonna be
covering how you can use TypeScript and React
and all the different things you need to know about it.
And if you can,
I highly recommend using TypeScript over prop types.