Welcome to an introduction to react. My name
is Bob Ziroll, and I'm here to guide you through learning how to build front end web applications.
using one of the world's most popular front end web frameworks react. But first, a little
background about me. I'm the Director of Education at V School, which is a technology education
school that teaches full stack JavaScript and UX courses to those looking for a career
change.
I've been teaching in the boot camp space since the very early days of boot camps
starting in 2014. Over the years of teaching and designing curriculum to help students
learn difficult topics in a very short amount of time, I've developed my own learning philosophy,
which I think would be helpful to share. First of all, the easiest way to learn something
is by doing it the hard way, there's truly no substitute for getting your hands on code
as soon and as often as possible. During our class orientation at V school, I typically
give an analogy about myself.
So I've recently developed an interest in woodworking. I've
read books, I've watched hours of YouTube videos, I've received new tools as gifts.
However, none of those things has actually brought me any closer to becoming a skilled
carpenter. It's not until I actually put in the hours of cutting, sanding, gluing, screwing
things up. And finally, eventually building things that I'm actually proud of that I can
say that I'm actually starting to become a skilled woodworker. As such, if you actually
want to learn react well enough to be able to use it, you'll need to be actually writing
react code. Most of the lessons in this course are followed up by an exercise that I fully
expect you to put in real time and effort into accomplishing on your own.
Now, if you
decide to breeze through them the easy way without actually doing the exercises, you're
actually kind of taking the hardest road possible to learning react. And along those lines,
you should really use the scrum platform to its full potential. Throughout the course,
I'll be having you pause the lesson and actually dive into the code making changes. But even
when I don't ask you to pause and play with the code, you should take the initiative to
do it on your own. And just be curious in general, doing this is going to help you avoid
what some call tutorial hell. And if you want some more information, there's a medium blog
posts that I've linked here in the slides. The idea essentially being that you should
get your hands on the code as much as possible. And by doing so actually do the things. Okay,
not just necessarily the exercises I asked you to do, but anything that you're interested
in curious about. And as I mentioned, scrubba is ideal for this sort of learning if you
use it the right way.
Another main point of my learning philosophy is that spaced learning
and repetition are absolutely key, this information to actually stick in your mind. And one of
the main tenants of spaced learning is that you don't just binge on the course, this kind
of goes in line with the concept of Tutorial How, where it can be the easy way out to just
binge on the course and feel like you're actually learning something when in reality, your brain
has been incapable of actually retaining the information. So as you're going through the
course, make sure that you take frequent breaks. And I don't just mean for five or 10 minutes
here, there. But finish a couple of key principles, practice them quickly, and then rest your
brain for the day. And when you come back to the course, don't be afraid to go back
to previous courses and review them. Yes, it will obviously take a lot longer to complete
the course that way, but it will be super beneficial to your learning.
Okay, I'll get
down from my soapbox for now. But I'll be reminding you of some of these things frequently
throughout the course. So for now, let's quickly cover what you'll actually be learning. When
we talk about react, we can't avoid the concept of components. components in react are the
core building block for making reusable pieces of HTML. And pretty much everything else that
we talk about deals with how to use these components to build the web applications that
we want to build. We'll also be talking about JSX, which is reacts proprietary wrapper around
JavaScript. And it simply lets you build components in a very familiar way, using the HTML syntax
that you're already familiar with. We'll also spend a little bit of time talking about styling
your components will get a chance to learn about props and how to pass data around your
application. And when we talk about props, we oftentimes talk about state which is how
to maintain and change data in your application. We'll talk about event handling, and how you
can have strong interactivity with your users.
We'll talk about lifecycle methods, which
help you hook into different timing events of your react components. We'll talk about
fetching data from an API using HTTP. We'll talk about forms and their role in creating
a good user experience. And there's plenty more that we'll be covering in this course
as well. Now, there's a few things that you should already know before taking this course. And honestly, it's just the basic building
blocks. htm Well, CSS, vanilla JavaScript, and ideally a little bit of the updated syntax
for JavaScript in iOS six. If you're feeling rusty on any of these topics, I've included
links on the logo that you can click, and it will take you to another free course here
on scramble to brush up on that topic. Okay, that's plenty of talking. For now, let's actually
dive into react. Let's take a quick look at some of the applications
that we're going to be building throughout this course, this should give you an idea
of what you'll be able to accomplish by the time you're done with this course.
The first
one is kind of the default required to do list application, it may seem a little bit
boring, but it actually covers a lot of the topics that we're going to be talking about
in this course. And of course, you can click an item to mark it as completed, and we see
some style changes and everything. And is kind of a capstone project to this course,
you're going to be building a meme generator. And the idea is you input some top text, some
bottom text, hit the button, and it will randomly choose meme image from an API that contains
meme images. Some of them are funnier than others. So get excited. React is really exciting
technology. And it's going to be an excellent tool in your tool belt as a developer. Alright,
let's get started. We're gonna jump right into learning about react. But first things
first, let's learn why we're going to be using the React framework, instead of just developing
something in vanilla JavaScript.
One of the things that you'll hear people talk about
with react is its speed, and how fast it is compared to web applications that are developed
in vanilla JavaScript. The way that react is able to do that is by using something called
the virtual DOM, we're not going to go into a lot of detail about the virtual Dom right
now. But if you're interested in learning more about it, I've included here a link to
a YouTube video with a pretty simple explanation of how the virtual DOM is different than the
way that web applications work when you're developing in vanilla JavaScript. So feel
free to pause the screencast and click on the link to watch that video if you want.
For now, it's enough to know that the virtual Dom helps make react work a lot faster than
vanilla JavaScript. Another really awesome benefit react gives us is the ability to create
reusable web components. And I'm going to talk about this through an example. Right
here, we have the bootstrap default navbar. If you haven't used bootstrap before, it's
just a CSS library that has pre written code that makes some elements look really good
for you.
But you can see that it's about 40 lines long, and it's pretty unwieldy and difficult
to understand. And if you were to include this in an HTML page with a bunch of extra
content in it, it would be pretty difficult to decipher, and everything would start to
feel pretty cluttered. reacts, web components allow us to take these pieces of HTML. So
this 40 lines that we see here, and put it into a component of our own, almost like a
JavaScript variable. In this case, we call it my sweet navbar. But you could call it
whatever you want.
And we can see that this is a lot easier to read, if you're coming
into it as a developer, to see exactly what is going to be where, in this case, the body
of my HTML will have a navbar on top, some main content in the middle and a footer at
the bottom. The ability to do this is really nice for reusing these components on other
pages if we need to, and for making our code look a lot nicer when we're working in it.
Another reason why react is so awesome that I like to include is that it's maintained
by Facebook, whether you care for Facebook or not. There are a lot of really smart developers
at Facebook whose job it is to work on react.
On top of that, because react is so popular.
There's a lot of contributors on their GitHub, which is open source who contribute to the
React framework, which means it's going to be evolving for the foreseeable future. And
last but not least, React is very hireable. At vi school, we focus our curriculum and
our efforts on the things that are most likely to get our students hired. And react is very
in demand right now. So if one of your goals is to get a job as a front end developer,
React is a great choice in terms of frameworks to learn.
So that's enough talking for now
let's jump into some code. Okay, we're just gonna jump right into the
code. One thing you're gonna want to be somewhat familiar with is es six, or ACMA script six
or ACMA script 2015. It's a slightly newer version of JavaScript if you're used to using
things like var. We're going to be replacing that with some
Yes, six stuff like const and lead. There are some videos here on screen buy that should
be able to help you learn that if you're not familiar with it, and you'll want to do that
before you move too far along in react because we'll be using a A lot of ESX in react, one
of the things we'll be using really often, in fact, in every react file we create is
the import statement. And so I'm going to import react from react.
And you can see over
here on the left, I have react and react Dom dependencies included in this project. So
I'm actually also going to import react Dom from react DOM. And the last thing we're going to do is use
react Dom's render method to render something to our screen. But let's stop and explain
this a little bit here, I'll get to why we're important react in a second. But for now,
I need to import react Dom so that I can use it in my line for code here, where I use the
render method. And what this is going to do is it's going to take two arguments, one is
going to be what you want to render. I'm doing this in pseudocode, obviously, so that it's
clear that this is not the right syntax. And the second parameter is, where do I want to
render it? react Dom dot render makes the second one really easy. Remember, everything
is going to have to tie back to an HTML page of some sort, the JavaScript we are going
to continue to write is simply going to be compiled down to or turned into elements on
a page.
And so you can think of it as being inserted into an HTML page of sorts. So let's
go over to index dot HTML really quick. You'll see everything in a basic HTML pages here,
including a link tag and a script. Don't worry about the fact that this is slightly different
right now, it will still connect correctly to our index dot j s.
One thing I want to
point your attention to though is this div right here with the idea of Route right in
between the opening and closing div tags is where react is going to be sticking everything
that we create, you can think of this as a container for our entire application. So back
in our index dot j, s, this, where do I want to render, it needs to point to the div with
the ID of route. And the way that I can do that is using a vanilla JavaScript document
dot get element by ID route. This way render looks at the first
parameter, which I haven't filled out yet that says, What do I want to render, and it
will stick it inside of the div with the ID of root.
Now let's look at this first part,
what do I want to render? Let's get rid of this placeholder. And let's just start with
a simple h1. And of course, we have to say hello world to refresh the browser over here,
and notice that we actually get an h1 with a Hello World in there. Now the astute of
you might have said, Wait a second, why are you putting an HTML element in the middle
of your JavaScript parameter, that's an obvious syntax error, JavaScript is going to think
that that is a less than symbol and that this is a greater than symbol and not know that
this is an HTML element.
Well, fortunately for us, the people that created react created
a little pseudo language, you could call it called JSX. JSX is very much like a JavaScript
rendition or version of HTML. In fact, we're gonna see that most of JSX looks almost identical
to HTML. With this few slight differences that we'll talk about along the way. There's
a lot happening under the hood with react, where everything is getting compiled down
to a plain JavaScript version of itself.
But for us, we can just pretend that this will
work just fine. And it turns out, this is why we need to import react from react because
the React library is the one that will enable JSX to work the way it's supposed to work.
In fact, you can see that if I remove the import react line, and try to save it and
refresh the browser, it tells me that react is not defined. Even though I'm not explicitly
using react anywhere in my code here. Under the hood, it's getting used to interpret the
JSX. Another point I want to touch on really quick is also dealing with JSX. It's important
to note that I can't render two JSX elements next to each other. For example, if I wanted
an h1 and a paragraph, you can see that it's already not liking what
I'm doing.
And if I were to save the page, it tells me that you can't have two adjacent
JSX elements. But instead they have to be wrapped in something so that it counts as
just one element with two elements inside. For example, I might choose to wrap this in
a div And I need to put my reactant back. And there
we go. Using JSX can take a little bit of getting used to, but it's much better and
nicer after you get used to it, then doing it the old way where you'd have to say things
like, var, my new paragraph equals document dot, create element paragraph, and add some
inner HTML, then take that paragraph and append it to a parent. That was very imperative.
Whereas now we're going to be doing things much more declaratively.
I also want to interject
right here that you should remember that the benefit of scrambler is that you can pause
this screencast and play with this code. So please take some time to do that. Not just
at the end, but also throughout the entire screencast. We're also going to be including
entire screencasts that are dedicated to you doing exercises, as mentioned in the first
video. So take some time, play with this, study it up and get ready for the upcoming
exercise. All right, welcome to the first practice of
this course, this is where it makes a lot of sense to you scramble over a regular video.
As we mentioned, we highly encourage you to actually give these practices and exercises
a shot. Sometimes it's really tempting to just skip ahead to the solution. But you're
only going to be hurting your own education. If you do that. So please give it a shot.
The way this will work is I will put an objective up on the screen sometimes some hints as you
see here.
And then I'll leave about five to 10 seconds of silence to give you a chance
to pause the video and actually try to accomplish the objective. If you get stuck, I recommend
that you not just skip ahead to the solution. But instead that you go back to a previous
video and relearn the thing that the practice is about, the more effort you put in, the
more likely This is actually going to stick. So let's take a look at this practice. Your
objective is to fill in the basic boilerplate react code needed to render an unordered list
to the page inside that unordered list, you can put three list items with anything that
you want in them, it doesn't really matter. The way that you'll know that it worked is
that it will show up in the little browser window on the right here. Since it may be
your first time working in react, I've included a couple hints that remind you of the steps
you'll need to take. So I'm going to leave some silent space now and go ahead and pause
the screencast and give this a shot.
Okay, let's go through the solution together, I'm
going to remove the comments that I have. And the first thing we will need to do in
almost every react file that we create is we're going to need to import react from the React library. And since this is our index dot j s, and we're
going to need to render something to the page. We're going to need the React Dom library.
Last but not least, we're going to use react DOM. We're going to use its render method.
And there are two parameters that we need to pass into render. The first one is what
do we want to render? Well, as the challenge said, we need an unordered list. And inside
that unordered list, we need three list items. Copy and paste this so we don't need to 123
you can see here, this is kind of looking pretty ugly.
We're going to see in the future
how obviously, we're not going to put our entire page here in the render. So I'm going
to move this on to its own line so that it looks a little more like regular HTML. If
you didn't do that, that's totally fine. And then I'm going to be really boring and just
put 123 in here. Okay, that's the first parameter. And the
second parameter is where do I want this to load into. If you remember from the last screencast,
we have a div with the ID of route. And that's where we want to place our application. So
in react Dom dot render, I need to provide get element by ID route, so that it will go
find that element and let react Dom dot render node, this is where I want you to put This
code and when we refresh the browser, we get our three bullet points with 123. If any of
that was confusing, I highly encourage you to go back to the previous video, rewatch
it, play with the code, come back, do this practice.
Again, mess with the code that I
put here, see if it works, the way you understand it, try to break it, etc. Doing that is going
to really help you understand react on a deeper level than just passively watching me explain
it to you. Awesome job. Let's move on to the next topic. In the last practice video, I mentioned that
you wouldn't want to end up sticking your entire application right here inside of react
Dom dot render. Imagine having a web page with hundreds of elements on it, this would
just be impossible to maintain. Back when we talked about why react was popular. One
of the reasons we mentioned was reusable web components, we're going to get a chance right
now to learn how to create functional components in react.
The reason they're called functional
components is simply because you create them by writing a function, I'm going to add some
space here and create a new function called my app. Notice here that I'm using the constructor
convention of having capital camel case for my component name. This is a very strong convention
that you should adhere to in react always have camel case and start your first letter
as a capital letter. And the really simple thing about functional components Is that
all you need to do is return the JSX that you want this component to represent. So in
our case, we can just take this unordered list and return the unordered list from our
functional component.
It's important to know that although in this case, it would work
without it, it's always a good idea to wrap this in parentheses. And then another strong
convention that I really like is to put everything on its own lines. This way, it reads a lot
more like HTML. Then in react Dom dot render, we can create an instance of our functional
component by placing the name of the component and wrapping it in basics tags, you'll notice
that I've made this a self closing tag, there are some instances where you'll want to create
components that can accept children elements. But for the next little while, we're going
to make every component a self closing component.
Now notice when I refresh, I have the same
thing that I had before. Though the same rules apply to our functional component as they
did in react Dom dot render, meaning I can't return two different elements next to each
other, like having another ordered, ordered list near this one. That just wouldn't work
because our component needs to return a single JSX element. And here it's returning to, you
can usually get around this by just wrapping everything in a div, or whatever other elements
that you want to wrap it with. In this case, we're just going to return the unordered list.
So maybe you can start to see the power in doing this, we're going to be able to create
our own components, which contain pieces of JSX, which represent HTML in our final product,
and we can start composing them together.
Here I have a component that I created rendering,
React elements or JSX elements or HTML elements. But as we create more and more complex applications,
I'm going to be creating components that render other components that I have also created.
Eventually, it needs to boil down to a regular HTML element. But sometimes that can happen
over the course of maybe dozens of your own react components that you created. Eventually,
as we start to create more and more components, we're obviously going to split these into
their own files. But for now, it's important to play with this and see what you can get
to work, what doesn't work and get a really good idea of how a functional component works.
As we move on, we'll start to make our file structure more and more complex. Now that
we've learned about basic functional components, let's put it to practice. Okay, let's get some practice of functional
components in. One of the things we really pride ourselves at V school when we're teaching
our curriculum is that we include a lot of spaced learning and repetition, which is a
principle of teaching that helps people retain as much information as possible.
As such,
like before, I haven't included any boilerplate code for you to start with. So it's going
to be up to you to build everything from Scratch during this kind of repetition is going to
be really good for your memory and should help you really understand the concepts. So
let's go for the objectives you have. First, you're going to set up the basic react code
from scratch again. And then you'll need to create a functional component called my info
that has an h1 with your name a paragraph with some information about yourself, and
an ordered or unordered list of the top three vacation spots you'd like to visit. Obviously,
since we're not going to be grading this or anything, you're welcome to change this to
whatever UI you'd prefer to present.
And then you'll need to make sure to render the instance
of your functional component to the browser. If you want a little extra challenge. Although
we haven't yet gone over how to style your components, feel free to search on Google
how you can add some style to your page. If it's enough of a challenge, just getting the
functional component working, then don't worry about that we're going to cover styling in
a future lesson. One less thing before I give you some space to pause the video and try
this out for yourself, I will once again get on my soapbox for the last time, I promise
that you should definitely actually do this exercise. If you're hoping to get from this
course, a real understanding of how react works just passively watching isn't going
to do it.
So please take the time to actually do this. Okay, I won't mention that again.
So go ahead, pause the video. And we'll pick up in just a few seconds and solve this together. Alright, so like last time, we need to start
with some of the boilerplate code, we're going to once again import, React from react, import,
React DOM, React DOM. And this is going to be a little out of order.
But I already know that I need to render something to the page, they already know that I'm going
to call my component my info. So I'm going to put an instance of my info right here.
And lastly, I'm going to do my get element by ID route. So that render knows where to
put the my input component. Okay, now the more fun part, let's build our function. Remember,
the one thing that the functional component needs to do is return the so to speak HTML
that we're going to be putting in the page.
In reality, as you know, it's actually JSX.
But sometimes it's helpful just to think of it as HTML. Since I already know this is going
to cover multiple lines, I'm going to put everything inside of parentheses. Now one
thing you may have tried to do just by habit is putting an h1 and putting your name and then going to the next
line and trying to put a paragraph. But think for a second what the problem with
this is. If you realize that the reason this is a problem, you may have tried to save this
and it says adjacent JSX elements must be wrapped in a enclosing div for an enclosing
tag. So I'm going to put this whole thing in a div. And it's a very common mistake to
make, especially as you're starting. So if you made that mistake, don't worry about
it. Okay, right here, we should have something that is at least working. So I'm going to
save this and see if it renders and there we go, we have a good start, all I need to
do is add my unordered list and put a few list items in there.
And I've always wanted
to visit Thailand, let's say Japan. And I've never been to the Nordic countries. So we'll
just add Nordic countries in general. And when I save this, I should see that my list
shows up in the browser. As a reminder, if you look in the very upper right, there's
a little left arrow.
If you press that and open the side menu, there's a chance to ask
questions on any pieces of code you're unfamiliar with or didn't understand. And I'm going to
be trying to check these as often as I can. So if you ask a question there, I'll try to
get back to you as soon as I can. Also, just because we finished this example, don't be
afraid to spend some time playing with this code a little bit more before moving on. Again,
the more you get your hands on the code and actually play with things, the more likely
this information is to actually stick and for you to be able to be productive with react.
Once you feel pretty comfortable with everything we've covered so far. Let's move on to the
next lesson. Let's talk really quickly about our setup here. Right now we have our functional
component inside of our index.js.
But remember, one of the main benefits of react is that
we get to create a lot of our own components. Eventually, we're not going to be able to
To put everything right here in this file, so what we need to do is we need to take our
my info component and move it into its own file. And it's a pretty good convention to
have each file contain just one react component. So the first thing I'm going to do is create
a new file.
And there's a quirk of Scripture right now that you won't be able to see me
typing this video, I'm going to right click up here by file since a new file and a dialog
box just popped up for me, and I'm going to give it the same name, my info as my component
with the same capital camelcase and everything. And you should see it pop up here now and
notice that the file, my info is spelled exactly the same with the same capitalization as my
component.
That's a really good idea, because it will make things a lot easier for you when
you're looking through a complex project tree. The next thing I need to do is take this component
out of this file, so I'm going to cut it, go over to my info dot j s, and paste it in.
There's a few issues here. You may remember in one of the early videos, we talked about
why we import react from react, even though we're not using react anywhere, try to think
if you remember why that is. The reason we had to do that was because of our JSX. We
used to have this component here and it contained JSX.
The computer won't know what this is
because it's not normally valid JavaScript. But the React library helps it become legitimate
JavaScript, which means we undo that back over in my info.js. Anywhere we're going to
be using JSX, we need to make sure to import react. Almost every react component you create
is going to have this line in it. The last thing we need to do is make this function
my info available to other places in my application. The way I need to do that is by exporting
it. If you don't feel totally familiar with import exports from ESX, that should be okay,
as long as you remember this export default and then the name of your component. But I
would also recommend that you go check out the free introduction to s6 course here on
screen. But now that this component is exposed through the export default, I'm going to go
over to index dot j s. And let's just Command S, we'll save this and see what comes up.
Notice it says my info is not defined.
Well, that's because we used to be declaring that
function here in this file and making an instance of it by putting these braces around it. But
now we're not doing that. So we need to import my info from my info dot j s, that's really
easy to forget that we can't just say my info dot j s. reason is because when imports don't
have a relative path, they will automatically look for a module with the same name that
you're providing.
This works okay with react and react Dom because they are third party
modules or dependencies that I've installed into this project. When it's one of my very
own modules, or one of my very own files, I need to make sure to provide a path. So
I'm going to say dot slash, which means from the current directory, look for a file called
my info dot j s. Another important thing to know about imports is that they assume that
you're importing a j s file or in other words, dot j s is the default extension. So I can
delete dot j s, and it will still work just fine. Now if I refresh, you get my component
back in the browser on the right. As your project gets more and more complex, it's going
to be really important that you have a good organizational structure. One simple organizational
structure I can employ right now is by creating a new folder called components where I'm going
to put all of my components in.
So I'm going to create a new folder. I like components.
And I'm going to drag my info dot j s into components and looking back@index.js what
do you think I'll need to fix here. If you notice that the path to my my info file is
now incorrect, because it's no longer inside of the root directory, I need to provide dot
slash components slash my info. And when I save this, everything should be working just
fine. Having a components folder is to me a little bit of an oversimplified way to organize
your application, because you're going to have so many components that you create that
you're going to need to find a structure that works best for you. And I'm not going to offer
one that works best. You'll probably even see me throughout this course using a few
different types. But each person has their own opinions about what the best organizational
structure is.
And it definitely depends on the project as well. Before moving on, try
playing with this a little bit. Maybe go change some code inside of my info, or maybe move
it into another folder or change the file name and see what you need to fix in order
for everything to keep working. Or if you're really wanting to be forward thinking you're
welcome to try and create a new component and nest that inside of my info, but this
is actually what we're going to cover in the next lesson. Once you feel comfortable with
everything we've talked about here, let's move on. In this lesson, we're going to talk about
parent and child components, our applications are going to be much more complex than just
having a single component my info, for example, render to the DOM.
Instead, you're going to
have a complex hierarchy of components that eventually lead down to JSX elements. I'm
going to start from scratch here just for repetition sake, so bear with me. Take a second to see if you can remember what
the next step is, you can start with something simple like getting HelloWorld as an h1 to
show up in our browser. In order for anything to show up on the page, we need to use react
Dom dot render. first parameter is what we want to render, so maybe h1 hello world. The second parameter is where do we want to
put that we'll be in an element called route in our index dot HTML. If any of that's confusing,
make sure to go back and review some of the previous lessons. But I'll assume that that
makes sense from now on. I refresh my browser, I get hello world. But we've moved past this
so far. Instead of having an h1 here, we put my info in less time. Instead, this time around,
let's create a component called app. An app is going to be an entry point into our entire
application.
In order for this not to fail, we need to import app. And in order for this
not to fail, because that component doesn't exist yet, we need to create it. So I'm going
to create a file called app dot j s. Notice it has a capital A because it's a react component.
In app.js, I need to remember always to import react. And before I forget, I'm going to export
default app works at this point app doesn't exist. So let's create it. Before I put anything
in the return, I'm going to refresh the browser really quick. And notice that there's a problem.
See if you can remember what we need to return here inside of this component. I need some kind of JSX element. So I might
put an h1 Hello, again, refresh. There we go. Or I could put any kind of other HTML
in here as well, maybe a div. Inside I have an h1, maybe something like
an unordered list. Maybe at this point, I decided that I want this to be an actual website
and I start putting things together.
So this top section might be a navbar. And below the
nav I might put a main section where most of my content will go. And at this point,
I would do something like add some styling to my unordered list so that this was more
like an F bar. As you can see, this app component is getting pretty large. And it's kind of
defeating the purpose of react, we talked about how we can take each piece of HTML and
put it into its own component. We're not really doing that very well here. Instead, we may
decide to create separate components for each little piece of HTML that we need on our page.
Take a look at this diagram to get a better understanding of what I'm talking about. Here
we're rendering the app component, but app may decide to render another component called
my info where my info may eventually render some kind of regular JSX element. Notice I'm
making a distinction between components and elements. elements are the ones that boil
down essentially to regular HTML code. Notice that here I have a lowercase D and Dev.
That's
a dead giveaway that this is a regular element rather than a component that I've created.
On the other hand, my info starts with a capital M. And that helps me understand that this
is a component that I've created. You may have heard of how the DOM or document object
model is oftentimes referred to as a tree where the HTML element is the most base root
of that tree. In our case, we can think of the app component as being the root of this
tree. And the app component isn't limited to just rendering my info. It could also render,
for example, a footer and that footer could render an app actual element called footer,
which has all of the HTML relating to our footer in it.
And if we have a footer, we
naturally probably want some kind of header. I've specified these as awesome header and
awesome footer. So it's not to be confusing with the regular footer element. And just
like app is rendering more than one component header may also render multiple components,
for example, a navbar, but also maybe a logo component. And those eventually would need
to end up as regular elements of some sort, in this case, an image element and the nav
element. Hopefully, here, you can start to see how our react application could become
more and more complex as time goes on. And this is only scratching the surface. So in
our sample app here, let's create a little footer really quick, going to create a new
file called footer dot j, s with a capital F, as seen here, which you'll need to import
react from react is always going to export the thing before I even create it just so
that I don't forget. Notice here the difference between the capital
F footer and the lowercase f footer.
As I mentioned before, the lowercase f footer is
the actual element that will get rendered to the screen. Whereas the capital F footer
is the component that I'm creating. It's just a function with a name. Inside here, I may
put, I don't know an h3. This is my footer. I've created this component. But notice it's
not showing up on our page. That's because our app is not rendering a footer anywhere
and need that footer in this file in order to create an instance of it. So I'm going
to import footer from dot slash footer. And maybe right under
my main section, I'll include the capital F footer that I just imported. refresh this
now. There's my footer element. At this point, I have kind of a strange mixture
of elements that are regular JSX elements being mixed in with components that I have
here. If I can, I really like to have this app component almost be like a table of contents,
where instead of having some elements in some components, it's mostly just components.
So
this might look like this. header, main content, and footer. And then I can go to each of those
individual components and see what elements those are rendering. Now header and main content
don't actually exist. But the point is, you can continue to nest your components as deeply
as you need, we're going to get a chance to practice this in the upcoming lesson. But
if you'd like you can spend some time trying to fix this code. Since header and main content
currently don't exist, go ahead and create them.
Also, before we move on, feel free to
click in the blue slides in the lower left to check out that diagram once again. Once
you feel pretty comfortable, let's move on to the practice. Okay, let's jump right into
the challenge, you're gonna set up a react app from scratch. Once again, what you're
going to render is the root app component, as mentioned here, and that app component
should render three separate components, each of which will have some kind of elements that
they render, first, a navbar component. Second, a main content component, and third, a footer
component. So give this your very best shot. Remember, you can always turn to Google for
help. Once you think you have this challenge, then move on with the video and we're going
to do this together. Okay, let's get started. We're going to import react from react, React DOM, React DOM, we're going to use react Gmes render method
to render a component called app ranks you select the root element app doesn't exist,
so we need to import it.
That file doesn't exist, so we need to create it epital a app dot j s. Remember, I like to
treat this file as kind of a table of contents. So we'll need to import react from react again. At this point, I'd like to just put something
on the page to make sure that I'm on the right track. Okay, at least not showing up tonight.
No, I haven't made a mistake up to this point. If you look back in the challenge, it said
to create a navbar main content and footer components, we could do this in any order,
we could first create the files, and then import them, we could import them and create
instances here and then create the files, whichever way you want to do and makes most
sense to you is totally fine.
I'm gonna finish my app component first, and then go create the components necessary for that
to continue working. And remember, everything needs to be surrounded in a single component,
because any given component can only return one element. Here, I'll put my header content and footer. Up GS needs to know about those first, so
I will import those. And those files don't exist yet.
So I'm going to create, you can
imagine as I keep creating new components that this is going to get pretty cluttered.
So I'm actually going to put everything into a components folder. drag my footer, header,
and main content into my components folder. I also need to fix my app j s. References
here. Okay, over in those files, I'm going to start creating those components. This will
just have a basic footer element. For now, I'm just going to fill it with some text because
it's not too important what's there. If creating these components is still a little bit foreign
to you, and you have to remember what step comes next, I'd recommend actually retyping
everything from scratch. Because I've done this enough times, I'm actually just going
to copy everything and paste it into header changing some of the references.
It'd be the same thing for main content. elicit
this just says main instead of main content, and that it's got a lowercase M. Hopefully
you understand at this point that this is because this is a regular, you could say HTML
element, main, header and footer are all semantic html5 elements. main content, however, is
something that I created. And so I couldn't say something like main content, because it's
not a real HTML element. Let me refresh the page and see if it's working. Okay, it's pretty
boring. And it looks like I forgot to put this is the main section.
Right. In the next
couple videos, we're going to learn about actually styling this because this is pretty
awful. And we want this to start looking good. Once again, feel free to pause the screencast
and play with the code that we have here. Or if any of this was still confusing, go
back to the beginning and try it again from scratch. Once you feel comfortable, let's
move on. Alright, so from what we've learned so far,
we can get started on our phase one of our to do application. So what you'll do is you
will initialize a new react app from scratch, you're going to render an app component in
the index js file here, which means you'll need to create an app component from scratch.
And your app component should render three or four checkboxes with the paragraphs or
spans or whatever kind of text you want next to it as if you're making a to do list with
some hard coded items already in it.
So pause the lesson here and give this a try. And then
we'll go over this together. Okay, so let's do this. I'm going to erase my comments here.
And as always, we need to import react from react, import, in this case, React Dom from react
DOM. We're gonna use react Dom to render an app component to the screen. And we want that
to be in the element with the ID of route. The app component doesn't exist yet. So we
need to import it. And this file doesn't exist yet. So I'm going to create it. We'll move
over to that file. Now. Where I want to also import react from react will create it our
functional component and want to remember to export it before we forget. This functional
component should return the div will need to wrap everything in it. Because
it can only return one element at a time. And inside this div, we will put our input
type checkbox. And our paragraph. For now we'll just put some placeholder text. You
save this and see how it looks. Okay? It's pretty ugly.
But we're going to get to that
later. And it said to do three or four times, so I'm just going to copy and paste these
two lines here. And there we go, we've started our application. That's pretty straightforward.
And the next time we see this, we're going to have learned about styling. And we're going
to add some style to this, so it isn't quite so ugly. So if anything was confusing, go
back and play with this. Again, try to do everything from scratch if you'd like, feel
free to post a question in the q&a section. And when you're ready, let's move on to learn
more about styling. This example is the same one that we finished
with at the end of the practice in the previous lesson. And I wanted to take some time to
learn how to style this. Now, there's actually a bunch of different ways to style things
in react. And we're going to start with the one that's probably the most familiar to you.
And that's just using CSS classes in CSS rules on those classes.
Let's drill down the tree
here and see where we can actually start putting some classes. You'll see on my index js, I'm
rendering an app component. And the app component is rendering a div with three other components
header, main content and footer components. And each one of those is just a basic component
that either has a single element as part of it with some text inside, let's focus our
efforts on styling the header. And normally, what you do in HTML, when you're going to
add a class to something is you add a new property called class. But one thing we need to remember right here
is that we're not actually dealing with HTML. Instead, we're dealing with a variation of
JavaScript JSX.
And something you'll just have to remember with JSX is that using class
as a property name doesn't really fly. Instead, we need to use something called class name with a capital N. A lot of places will tell you the reason that
you have to do that is because class is a reserved keyword in JavaScript. But the truth
is underneath JSX is just using the vanilla JavaScript Dom API. And if you've ever used
the vanilla JavaScript Dom API, you'll have something like document dot get element by
ID, something. If you wanted to add a class to that, you could say dot last name, plus
equals and then add a new last name. I prefer class list myself because it has properties
that you can use to add and remove classes. But that's beside the point. Class Name is
an underlying JavaScript Dom API property. And so using class name as part of our JSX
is simply a way to access that Dom API under the hood, which is what JSX and react is doing.
That's just a little bit of extra background that you may or may not be interested in knowing.
But the point is, all you need to do is wherever you normally would say class in HTML use class
name instead.
Here I'm going to say class name equals F bar. I'm going to delete this before it becomes
a problem. Then over in my style, that CSS, I just need to select the navbar and include
whatever styles I want. For example, I might change the background color to purple. If
I save and refresh this, you can see that now the background color is purple. I'm going
to copy and paste in some style since this isn't a course on CSS, so that we can get
something that actually looks pretty good.
Okay, the only thing I've done here was added
a zero margin to the body so that it went all the way to the edge, and a number of styles
to the navbar. If you're interested in actually checking this out, feel free to pause the
video. But the point is everything that you normally do in CSS is going to be essentially
the same as you do here. The only change we've made so far remember is that we have to use
class name instead of class. One of the other things to keep in mind that maybe tricky to
remember at first is that you can only apply the class name attribute to react elements
like header or paragraph or h1. If you try to apply class name to a component that you've
created, such as header or main content, it's going to do something a little bit different
than you think. And we're going to talk more about that in the future.
But for now, just
remember that the only thing you can apply classname to are react elements and not react
components, the things that look basically like regular HTML. Another thing that can
be kind of tricky in the beginning is if you're using something that requires different levels
of your tree hierarchy, like Flexbox or CSS Grid, where you need to know which items are
the flex container and which items are the flex items. be tricky looking at your component
to know exactly how that works. For example, if I wanted to make this div a flex container,
and I wanted to specifically style one of the items they're in, I would need to go to
the header component or the main content component.
And look at the elements, they're in order
to give them the class names that are necessary. For example, if I go to header js, this header
element will be the direct child of this div. Think of it as react, taking the contents
that this header component is returning, and copying and pasting it into this place. When
you create your react applications and you inspect with the dev tools, you'll see that
this is actually how things end up in the DOM tree. So take some time to play with classname.
In this project, see if you can style the main section in the footer a little bit differently.
And once you feel good, let's move on to the next lesson.
Before we get too much further, I wanted to
cover some caveats about the way that I tend to write my JavaScript, you may have noticed
that I tend to leave out things like semi colons, you may be super used to putting semicolons
everywhere at the end of a statement, I personally have recently decided that I kind of hate
them. And so I've been removing them from my code. Obviously, there's still some places
that you simply can't avoid them. For example, when you're writing a C style for loop, zero
semicolon that's necessary in order to separate the three different statements on one line.
But for the most part, at the end of statements, they're not really required, and they won't
break anything by not having them there. This is totally a personal style decision. And
like I said, one that I've only recently made.
In fact, it's such a strong habit for me that
I may accidentally put some semi colons in future videos. Another personal preference
is although ESX technically gives us the ability to put arrow functions everywhere, we used
to have the function keyword. For example, I can say const app equals an arrow function.
And one of the benefits of this is actually that I can actually just wrap everything in
parentheses and get rid of my return. And in this case, I could even simplify it like
this. I've either not yet gotten used to this syntax, or I simply don't care that much for
the look of an arrow function.
I think they're extremely useful in certain instances, for
example, whenever you normally would put an anonymous function or when you need to write
a class method, which we'll talk about later. But my personal preference is to keep the
function keyword and it just to me makes it look a lot more like a regular function component.
There's a lot of people who will disagree with that. And I'm totally fine with that
I totally understand the preference for doing it as an arrow function. But me personally,
I tend to keep my function keyword in there for my functional components. I'm not going
to necessarily advocate for one way or the other. So that's totally a decision that's
up to you. Okay, I just wanted to get some of that out of the way. Let's move on. Before we can move on to talk about inline
styles and some dynamic styles, we first need to understand how JSX and JavaScript play
together, we saw that in the middle of our JavaScript, we're able to return something
that looks like HTML, but we've discovered is actually JSX.
What if I have a variable
that I want to stick inside of my h1? Maybe for example, I have a first name and the last
name. And instead of saying hello world, I want to say hello, Bob's a role. Well, I might
be tempted to say hello, and then first name, plus space plus last name. But I'm assuming
you can figure out exactly what's going to happen here. When I save this. It literally
interprets every character that I typed as if it were the text inside of the h1, which
is pretty much exactly what we should expect it to do. So how do we jump into JavaScript
while we're in the middle of our JSX, they actually made it really simple. All we have
to do is surround any JavaScript that we want to be interpreted with curly braces. And once
I refresh this, you'll see that it actually interpreted everything inside of the curly
braces as JavaScript. The way I like to think of this is we're looking at JavaScript, JavaScript,
JavaScript, JavaScript, and now we're in JSX land.
Once we're in JSX land, which actually
started with this less than symbol, everything will be treated as if it were regular HTML,
meaning any text inside is going to be literally interpreted. However, as soon as we want to
get back into JavaScript, we put a curly brace and now we're back into JavaScript. Learned
JavaScript JavaScript JavaScript, closing curly brace tells me we want to leave JavaScript
and go back into JSX. And you can do pretty complex JavaScript operations inside here.
Since we've mostly converted over to the e6 syntax, I'm actually going to change this
to the string templating syntax of ESX, where you put backticks, and then $1, sign curly
brace surrounding any variables that I want to show up, then I can just put a space itself,
and that will be treated as a literal text space, then $1, sign curly braces again, last
name. And I save that and you see, we get the same result over in the browser. Because
this is just regular JavaScript inside pretty much anything that I could regularly do in
JavaScript I can do inside of these curly braces.
Let's look at one really simple example.
Maybe when it's morning, I wanted to say good morning. And when it's night, I wanted to
say goodnight, without actually having to come in and change the code manually. Well,
I can just do some simple JavaScript to set that up. I'm gonna speed this up really quick,
but we'll get a chance to explain it in a second. Here, you can see one example where
I've created a new date instance, and simply put in my h1 It is currently about. And then
in JavaScript, I got the hours and did a modular 12, so that it would be in a 12 hour clock
system.
Alternatively, I could check the current hours for what time of day it is, and set
a string equal to either morning, afternoon or night, which let's try that out right now.
So here, all I did was set a variable called time of day, and did a simple if else, to
check what time of day it was. Then down here, I simply said good, jumped into JavaScript.
And said time of day, when I refresh this, I get good night.
Because it's nighttime where
I'm recording this, hopefully, you can start to see the possibilities that this brings.
And we're gonna see as the course moves on that this is actually really useful. We needed
to see this right here simply so that in the next video, when we talk about inline styling
with the style property, the way that we have to do that, we'll make a little bit more sense.
Feel free to mess with this, there's some pretty fun things you can do. Once you're
ready, let's move on. Let's pick up really quick where we left off
in the previous video, we created this little application to tell you what time of day it
was.
Essentially, we want to add some styles with inline styles this time, and we're going
to see why this might be the way we choose to do it instead of using a class name. Normally,
to do inline styling with HTML, we simply put a style property and set it equal to whatever
CSS styles we want. Maybe we want to change the color to be this kind of yellowy color
that I just grabbed. Well, let's see what happens when I try to save this. Let me open
the console. Notice that it says the style prop expects a mapping from style properties
to values instead of a string. We have to remember here that we're not actually inside
of HTML. So sometimes the rules are going to be a little bit different. In this case,
JSX expects style to not be a string, but instead to be an object, a JavaScript object.
So I'm going to delete this and put in an object and say, color colon, and then as a
string.
That color again, notice that I have some syntax problems. Remember, anytime I
want to change from JSX into JavaScript, I need to wrap my JavaScript with a set of curly
braces. This can be a little confusing at first, because objects are also wrapped with
curly braces. But in order for this to be a JavaScript object, I need to wrap it in
curly braces. So we end up with two sets of curly braces. Now when I refresh this, you'll
see that I get my more orange or yellow color as the color of this text. If I want to add
additional styles, because this is an object, I just add another key value pair. For example,
maybe I want it to have a background color of this somewhat red or color that I got. Well,
what's my problem now take a second to see if you can figure out what's going on.
Remember,
because of this set of curly braces over here, we're actually inside of JavaScript. And inside
of JavaScript, I can't have a dash in the middle of my property name. I technically can in regular JavaScript by surrounding this
with quotes, but that's beside the point. Because of this inside of the object where
we're defining our styles. We're going to change anytime that there's a dash, we're
going to get rid of the dash and make everything camelcase. This right here is the legitimate
style object. Let me refresh. And you can see now we have a different background color.
As you might imagine, this style object right here may end up getting longer and longer,
in which case this h1 line is going to become really long and it looks a little bit ugly.
to split this out onto separate lines, so what I prefer to do is actually make a separate
variable. Let's just generically call it styles for now. And put this entire object into that
variable. We can split this onto its own lines without it looking funny.
Inside of my curly
braces here, where I'm now inside of JavaScript, I can just put variable name. And that's going
to be exactly the same thing. Notice when I save, it continues to work. What's nice
about this is as I continue to add styles, it doesn't clutter up my h1 down on line 24.
There's a number of little tiny quirks that we have to remember when we're doing these
style objects. For example, anytime I have a measurement that's going to be in pixels,
I technically can just put the actual number value in place, and the
default will be pixels.
So when I save this, you see that I get a slightly smaller font. But 200, I get a really big font, and so forth.
I can also still specify pixels. But obviously, that's not going to work with numbers by putting
200 pX because that's not valid JavaScript anymore, I need to turn this into a string.
And now it's valid JavaScript again. And then anytime I want to use another unit like M
or VW or percentage or something like that, I will also put that as a string. Also notice
once again, that I've replaced the dash with a camel cased version of font size. There
are some pretty interesting limitations with this. For example, it looks pretty funny when
you have to add things like vendor prefixes. But there's other things like pseudo selectors,
such as colon hover, that become actually impossible to do inside of these inline styles.
If you need something like that, for now, you're better off just doing that in CSS and
using class name.
And in the future, you can learn about really cool styling libraries,
such as styled components. For now, we're just going to keep it simple and stick with
either inline styling or using class name and using CSS styles. You may ask yourself
why you would ever want to even use an inline style like this. Well, one reason is that
you may want something to be more dynamic, in which case JavaScript would actually determine
what the styles are. Let's take a quick look at what that might look like.
Notice what
I've done here, where I moved the styles up here above my if else, and set a default font
size of 30 pixels, then I let my if else in my JavaScript actually determine what color
the font is going to be, I changed not only the time of day string, but I also changed
the color property of my styles object. Because it's an object, I can access and create properties
just by using the dot syntax. If it's morning time, I use this color.
If it's afternoon,
I use this color instead. And in any other case, when it's night, I use this color instead.
Because I'm recording this at night. This red color is the one that's actually showing
up. But let's see what happens when I create the date not for the current time. But instead
for a time that was this morning. This is the year, a month today. Let's say it's 10am. I save this, notice that
we get instead the color that is the color for morning. If I change this to, let's say
15. And it's hard to see, let me choose a different color for the afternoon. You can see a little more clearly this is
choosing a different color for the afternoon. This may be a little bit contrived. But the
point is we can have dynamic data that actually changes the way that our hard coded components
display. Take a second to try and think of different things that you may be able to accomplish
by having these kinds of inline styles.
I'd also at this point, recommend spending as
much time as you can to really solidify the stuff that we've covered together. So far,
we're about to come up on a topic that typically is a little bit challenging for some people
to really help you to make sure that you understand everything we've talked about up until now.
In the next lesson, we're going to talk about a concept called props, and how we can make
our components quite a bit more reusable. Props is a super exciting topic. And we're
about to get into parts of react that make it extremely useful. So get excited. And let's
move on to the next video when you're ready. Alright, so let's pick up where we left off
with the to do list. Now that we understand Parent Child components and how a parent component
can render a child component, and we understand how to inject some styling into our react
apps.
Let's progress our to do list forward a little bit. So before we get to styling,
what I want you to do is to take these input and paragraph pairs, and I want you to put
them into their own component called to do item. For now it will still have just this
hard coded placeholder text here paragraph And later, we're going to learn how we can
actually make those different.
But that'll be the first thing to start with. And then
essentially, you have a blank canvas to paint whatever kind of picture you want, you can
make this look as traditional or as weird as you'd like. So go ahead and hit pause and
give that a try. Alright, so the first thing is moving each of these into their own component.
So I'm just going to copy this and create a new file called to do item dot j s. And
while I'm still here, I'm going to import the new item from that file. Let's go over
to to do item, we'll import react from react, create our functional component, we'll just
return the thing that we copied before. And remember, I can only have one element that
I'm returning at a time.
So I'll wrap this all in a div. And then over in app j s, we
don't need these anymore. But instead, we can just create instances of our to do items.
And everything looks the same. Now since this isn't necessarily a course on styling with
CSS, I'm basically going to cheat right now, I'm going to set myself up by creating a class
here of to do list. And over in my to do items, I'm going to give this div a class name of
your item. And I'm basically just going to paste the styles that I've already created.
Okay, and you'll notice that let me make this a little bit bigger. And notice that I just
kind of came up with a cool little paper looking stack and have a checkbox next to each one
that's a little bit prettier, with nicer font and little separation and so forth.
Obviously,
you're welcome to pause this and look through some of the styles that I have. But it's really
nothing too fancy. And since I'm not really a wizard at CSS, stuff like this, with the
cool little effect on there, I basically just found online. main takeaways, though are to
remember that if you want to apply class to your elements, you'll need to use class name
instead of class. And if you wanted, you could apply some of these styles just right here
in line. So with a little bit of CSS styling, our to do list is already looking a lot better
than it was. Now we are checkboxes do technically check and uncheck but what we're going to
do is make sure that when we check these, some actual data is changed, which will allow
us to do something cool, like put a little strike through through these texts.
Once you
feel pretty comfortable with this, let's move on. Let's talk first about the concept of props
in react. To do so we're going to look at just a regular HTML file, notice that this
has nothing to do with react. This is just a basic index dot HTML, I want you to take
a close look at the three elements that I've put inside the body, the anchor, the input
and the image and think about what's actually wrong with them right now. None of these things
are actually going to do anything important. anchor tags need an H ref for them to make
any sense at all. This way, the HTML spec can define the anchor tag once and allow us
the ability to change the place that the link sends us. For example, here, I may put a link
to Google. Or obviously, wherever I want to send the user to in this link, an image tag
is very similar. An image tag alone without the source property is pretty useless. An
image element needs a source in order to function correctly. This may either be the path to
a local file or the URL to an image hosted online.
In those two examples with anchors
and images, the href and source properties respectively, are required. Inputs technically
will show an input on the page. But I can beef it up a little bit by adding additional
properties such as placeholder, or the name property, or the type property type is an
interesting one. Actually, it allows me to change this input to be multiple different
things. For example, this may be a radio button or a checkbox or a regular input. That input
could be either text or an email or a phone number, and even changing it to a submit button.
A lot of times these are called attributes. But another legitimate word for it is a property.
If this simple concept in HTML makes sense to you, which I assume by now it probably
does. Understanding props in react is not too difficult. Instead of using the built
in HTML tags, since we're creating our own components, we can actually make it so that
we can allow properties to modify the way that the component acts.
So in the next video,
we're going to see how we can actually do that. I want to make one more conceptual point before
we actually get into using props with react. This here is from the YouTube homepage. And
while I'm pretty sure the YouTube homepage doesn't use react since Google is the main
backer of Angular, the concept will remain the same. Think for a second how this page
may be developed in react, something you'll begin to get really good at doing is noticing
how something can be divided into separate components. For example, notice that each
of these separate pieces of the page are all very similar in their own way. If you notice,
each one of them has an image on the top that takes up about the same amount of space. Each
of them has a title, which is in bold and appears usually directly below the image.
Each one has a number of views.
Each one tells you how many days ago it was published, each
one has a little timestamp inside of the image that tells you how long it is, you can imagine
that the creator of this page didn't actually go into the code and copy and paste this a
bunch of times. If this were developed in react, then you can imagine there might be
a video title component that is created. And that component has a number of components
inside such as an image, maybe an h3, a little timestamp box, and so forth. The main point
of what I just said is that it will be a single component that's developed once, but we need
to make it so that that component can change depending on the different properties such
as the image URL or the title.
That's what we're going to be working on in the next video.
Right before we move on, though, I wanted to get you used to the idea of thinking in
terms of react back a few lessons when we talked about parent and child components,
that tree can go as deeply nested as you want. In fact, you can see here, we have different
lists. So there may be a component that is a list component, which renders a number of
video title components, which in themselves render an image and an h3 or whatever, like
we talked about. Also, over here on the left, you can see a number of things on the page
that may have only been developed once as a single component. And then given a property
of maybe a little image on the left and the text that should show up as part of the link.
Hopefully, you can see how the idea of web components and reusable HTML is really powerful.
And this can help you understand why frameworks like Angular and react and Vue JS are very
popular.
So that's enough with the conceptual let's move on to some code and see how we
actually do this in react. So let's take a look at an example where it
would be really nice to have separate components, but not just separate components. But those
that could take different attributes or props in order to make them a little bit more dynamic.
Here, I've created just a really basic contact card list, where it shows the image of the
contact and a name for the contact the phone, and email.
Right now I only have four contacts
and my contact book. To start, we know that it would be really nice to take these pieces
of repeated HTML code and put them into their own components. But from what we've learned
so far, we would actually have to create four separate components, one for each individual
contact, but that's not really gonna work for us. So first things first, let's actually
create the component. And then we'll learn how to make it more dynamic. We're going to
create a new file called contact card, Gs. And I'm going to take this div, which is the
repeated div across these four contexts, and just copy it. And I'm going to start a new
component. If you'd like, feel free to pause the video and see if you can figure out how
to do that. As always, for components I'll need to import react from react Yak. And I'm going to export the function
that I'm about to make my spacing here. And this is a great start. The problem with this
is that it has a hard coded image source, a hard coded name, hard coded phone, a hard
coded email and so forth.
Instead, we're going to want to figure out a way to make it so
that this contact card when I make separate instances of it will be able to take as properties
the different information that I'm going to put into these places. Another quick conceptual
point you can think of has to do with functions, which actually mirrors pretty nicely what
we're doing because we are using functional components. When you create a function, let's
say add numbers. Maybe this function returns the result of one plus one. Well when I want
to do an operation with one and two, or one and three or two and three, I'm not going
to want To create separate functions for every single one of them.
Instead, we use function
parameters, maybe a and b. and make it so that any two parameters we pass into this
function, we can get a different result depending on those inputs. The same concept of adding
parameters to a function to allow the function to be more reusable is the same thing we're
going to be doing with react components. Let me delete this. In order for us to illustrate
this, let's go over to App j s. And I want to be able to replace all four of these with
the individual information for each component. But let's start by actually putting the component
in there, I would like to be able to say, I want a contact card here. And I actually
want four of those.
Well, for this not to fail, I need to import contact card from that
file. And now comes the time to actually pass down individual information for each contact
card, just like we did with regular HTML where you pass in an attribute or a property right
here, we're going to do the exact same thing, except this time, we get to decide what the
name of that prop is. For example, each of these contact cards has four pieces of dynamic
information, the image URL, the name, the phone number, and the email address. So let's
pass a property down for each one of these, it's actually pretty simple, I'm going to
say name, equals, and then put in the name that I want this contact card to use. And
I'll do the same for the other information, image URL on an email.
Now, for me personally, when these start to
wrap on two separate lines, I like to put everything on its own line and in rented, I'm gonna do that really quick. I'm going to go through and do this really
quickly for the rest of the contact cards, putting each of these individual contact card
information into properties of the contact card component. Notice when I just refreshed even though I've
put separate different pieces of information into each one of these contact cards, I'm
still getting Mr. Whiskers send four times. The reason is a contact card currently has
hard coded values inside of itself. But we're passing in separate props, name, image, URL,
phone, and email. So let's see how we can inside of contact card j s access the data
that we're passing down to the contact part, over in contact card, one thing that we haven't
put in quite yet, is inside the parentheses here in this function, it's going to take
a parameter called props.
Because it's a function parameter, you technically
can call it whatever you want, but it's a strong convention to call it props. Props
is an object that has properties of that object, each one being a prop that you passed in,
or rather, the name of the prop that you passed in. What I mean by that is, we will have inside
of contact cards will have props dot name, and props dot image URL, over in contact card
j s. Let me just console log ops. Take a look. Take a look at this, we got four console log
entries, the reason being we have four instances of our contact card component.
And the props
are an object with a name, image URL, phone and email properties. This means now inside
of my code, instead of having hard coded values here, I can use the property of the props
object that's coming in. So I can say source equals, and I can't just say props dot image
URL, think for a second why that doesn't work. And think of how you might fix it. Remember,
when we're switching between JSX and JavaScript, we need to use curly braces around our JavaScript.
We can do the same thing for the other values here as well. Props dot name. Here, I can
leave phone colon space as a hard coded value. And then just replace this with props phone
in the same thing with the email. Now when I refresh, I actually get my four separate
contact cards with the individual information. I'm going to delete this console log so it's
not cluttering things up. And as easy as that I now have a component that is reusable in
a lot of different ways.
Now at this point, I want you to think What would my component
look like if my contacts had, say 50 properties to them over an app js, each of these contact
cards would end up getting pretty long, right? I would have a prop for each individual thing
that I'm saving about that contact, which like I said, perhaps could be something like
50 different properties. Another legitimate way to do this is instead of passing down
each part of this person or contact as an individual property, I could pass down an
object that was the entire contact.
For example, instead of name, image URL, phone and email,
I might simply pass down a prop called contact, whose value is an object. Remember, I'm going
between JavaScript and JSX here, so I need to put a double set of curly braces, the first
one getting me into JavaScript, inner one being the object itself, that object would
have a name, an image, URL, phone, and an email. This technically would allow me to get rid
of these four properties, and just pass down the single property called contact. Now, this
may not actually look better than what we had before. But we're going to see eventually
how this data isn't usually hard coded in like this, but rather comes from something
like a JSON file, in which case, it can be really nice to pass down the whole contact
as a single prop. However, our component is going to be broken now. Notice when I refresh,
the only thing that shows up are the phone and email hard coded text.
Pause the video
and try to think why that might be. The reason is over in contact card, we're receiving a
props object, and we told it that that object would have a property called image URL and
phone and name and email. However, for our first contact card, we're no longer passing
a phone, email and name or image URL. Instead, we're passing a prop called contact, which
is an object. So let's go over to contact card, pause the video and see if you can fix
this to work. If you're having trouble, one thing that may help is to console log prompts. See what's actually showing up here.
Okay, now that you can see this console log, give it a shot again. Notice the first one is not receiving a name,
image URL, phone and email like I mentioned before, but instead is only receiving a single
property contact. And that contact property is an object, which means I would need to
change everything to props dot contact dot image URL, and props dot contact dot name.
And the same for these other ones. Now, of
course, when I refresh, I'm going to have a major problem because my other components
aren't receiving a prop called contact, therefore, it's undefined. And I'm trying to access the
image URL property of undefined. So this won't just not show up, it's actually going to crash,
which means I need to go back to App j s, and fix each of these other contact cards.
I'll spare you the monotony of watching me do that and speed this up. Okay, that was
pretty tedious. Let's refresh and see if that works. Okay, now we're working again, our
contact card is passing down a single prop called contact, which is an object that has
all of the properties that we want. Again, normally, this won't be hard coded, but instead
would be something you get from a data file, such as a JSON file, which we're going to
cover in a future lesson. And over in contact card, I'm receiving all of my props as an
object called props.
And since I only pass the single prop down, I have props contact,
but props contact is an object. So that has properties itself like image, URL, name, phone,
and email. Again, this concept can be a little bit tricky. And I totally understand if this
didn't make sense the first time through. As I mentioned before, the sweet benefit of
schema is that you can pause this and actually mess with this code. So even if you feel like
you understood this, I'd really appreciate if you pause the video and go through and
actually mess with this, change the data over in app j s, see if you can then reflect it
to show up correctly on contact card. Also, feel free to go grab different image URLs
and put those in and see how it affects the code. More you mess with this more likely
you'll be to actually understand it well enough to implement it yourself.
To Go ahead, give
that a shot. And only after you feel really comfortable with it, move on. Okay, I'm sure this has been pretty obnoxious.
But this is the very last time I'm going to ask you to do this. I want you to create another
react app from scratch. Obviously the repetition is going to be really good for you and what
this react app should do is render an app component which should be in its own file.
And the app component should render five joke components, we can see that this is going
to help us practice the parent child component tree, it's going to help us practice putting
components in their own files.
But the main thing we're going to practice is passing props
down through the joke component. So each joke component should receive a question prop and
a punch line Prop, and then render those to the page however you want. That's just kind
of the basic part of the practice. But I've added a little extra credit section, which
I'd really encourage you to try. So in this case, if your component does not receive a
question prompt, you need to think how might you make it so that it only shows the punch
line instead? For example, if you've hard coded in a question, text that says, a question
colon and then appstack question. Obviously, this syntax is incomplete. But how are you
going to make it so that you don't have question, colon, and then an empty space? Also, while
you're at it, see what happens when react receives a prop that's undefined? If you don't
have a question colon, and you're also not passing down a question Prop, see what happens.
And while you're at it, spend some time practicing the style, if you joke component, make it
look good.
So pause the video do this practice. And we'll go through this together in just
a few seconds. All right, I'm gonna delete this. And I'm
gonna actually leave some of these comments here, just so that I can remember exactly
what to do. We know we need to in a basic setup, import react, and react, import react DOM, React DOM, when to use react DOM. To render our app,
we're gonna put it at the root element.
Don't have apps, I'm going to import app from a
file called app that doesn't yet exist. And I'll create that file. Now. I put a app.js.
Over in that file, I need to again import react from react for the app component that I'm about to make,
wrap everything in a div. Okay, and here, we're going to render our five joke components, that should be capital J 2345. Now for this to know what I'm talking
about, when I am trying to create an instance of a joke component, I will need to import
that. And that doesn't exist yet. So let's make that I'll create a file called capital
J joke. dot j s. And over in joke j s, let's again, import react from react. Default joke. And
before I get too deep into playing with props, I'm going to just have it render something
simple just to see if it's working.
I may have forgotten
something. But let's check this out. Okay, yep, my five highs on the screen, which
means my five jet components are working. React Dom dot render is rendering the app
component, the app component is rendering a div with five joke components. And the joke
component is just rendering an h1. And that's how I'm getting five highs on the screen.
And that's the tree that we're working with. While I'm still in this file. I'm going to
work on the props here.
So I know that I need to pass in a variable. I'm going to call it
props because that's the standard. And let's start with something simple. I'm going to
render a div with maybe a couple h threes inside. One will have the
question. One will have the answer. If you had gotten stuck anytime before this, I'd
really like you to pause the video and go review these things that we just went over
and then try it again from scratch. You can go back in time to the beginning and actually
try to build this out yourself. Then once that makes sense. Come back to this point
and move on. Now if everything did make sense up to this point, pause the video here and
see if you can figure out how are we going to get the question from our joke that's being
passed in. Of course right now.
It's not yet being passed in the wind it is how are we
going to place it right here. Remember, we're inside of JSX right now. So I can't just say
props question because that would literally put the text prompts question here. When I
want to go inside of JavaScript, I need to surround it in curly braces. Notice that I
get nothing On the screen, think for a second why that might be. Let's actually console
log prompts question. Open the console and see what shows up. That's what I get. No.
That's because this joke component when I'm creating instances of it in my app, I'm not
actually passing in a question or a punchline prop. So when react tries to render a component,
and we're not passing it any props, everything will be set as No. What's really cool about
react is if any JavaScript inside of JSX evaluates to something like undefined or no, it simply
won't display it.
This right here is going to be something we need to figure out how
to fix when we have our joke components that don't take a question prop. But for now, let's
assume that they all have a question and an answer or a punch line. So over here, I'm
going to also add props dot punch line, and they can delete my console log here. Let's
go back to App j. s. And let's actually provide a question in punch line for every one of
these jokes.
As I mentioned in a previous lesson, I prefer
to put these on their own lines, if they start to get so long that they're wrapping around. You may decide this isn't your style. And
that's totally up to you, I still go back and forth as to whether I want this closing
bracket to be on the previous line or not. So let's refresh this and see what we get.
Cool. Everything's a little bit squished together. So you may decide to do something simple like
at the end of a joke, you may put a little break tag, or maybe something like a horizontal
rule.
But obviously, however you want to style it is totally up to you. And there we have
the basics of the first part of our exercise. Now, as we see in the extra credit, some jokes
are only a punch line with no question. And as it stands, I have this hard coded word
question colon space here. I provide a joke that doesn't have a question. Like my favorite
one only has a punch line. See, when I render this, I get a question with nothing there.
We're going to talk in a future lesson about conditionally rendering parts of our page.
But for now, think about the way that we style our page and see if you can think of a way
that we can make this disappear if there is no question. So video and give that a shot.
Again, there's actually going to be a real way we do this with something called conditional
rendering. But for now, you may find a way around it where you can say I want this h3
to have a style feed display of none under certain circumstances.
But afraid here I use
the ternary operator to decide what that should be. inside of my object I could say essentially
is props that question a thing? Is it truthy, if so displayed in the regular block format,
but otherwise displayed is none. Notice that my first one has an h3 that is now displayed
none because it no longer has props question. If you're not very familiar with ternary,
I highly recommend you go spend some time learning about them because they're actually
used quite often in react. Another slightly more concise, but perhaps more confusing way
to write this would be instead of using a ternary.
And having a default of its own default,
like an h3 being display block. We can get rid of that. And we could actually say if
there isn't a proper question, then we want to display
none. But otherwise, basically ignore this rule totally. If you're not familiar with
using the double ampersand in this way, we're going to talk about it in a future lesson.
But just know for now, this totally works. You can see over in my browser, I have just
an answer to my joke that doesn't have a question in it. But the question does show up in all
of these other instances. Now if you look at my joke that doesn't have a question, it
doesn't stand out very much. Maybe you might decide that you want your answer only jokes,
your punchline only jokes to look a little bit different maybe to be grayed out or to
be a totally different color or underlined.
I don't know something, also video for a second
and think how you might do that using inline styling and JavaScript the way that we did
in line six. Maybe what I might do is on my answers, h3 is add an inline style with an
object it says the color should be and then do something similar to what I have on the
question art on the h3 above where I say if there is no props dot action, then I might
want the color to be I don't know some kind of gray This is pretty contrived. But you get the
idea, we can start using the different props that come into our component to display things
differently. And as such, our joke component is now more or less reusable, we can add jokes
that just have punch lines and jokes that have both questions in punch lines. And automatically
the joke component knows how to style itself based on the incoming props. And that's pretty
much it for this practice, feel free to pause this and play with this as much as you want
before moving on.
Alright, so we're going to pick up where we
left off in the previous practice with our app component rendering a bunch of joke components.
Some of these have the punch line in them, and some of them have a question and punch
line. But you can see right now that they're hard coded into our components written directly
as text. In reality, most of the data that you'll be displaying on a page will actually
be coming from some kind of HTTP call to an API, where there's a server that hosts the
database, and that database and server are returning JSON data to you.
We haven't quite
gotten to the place where we can make API calls quite yet. So what I've done is I've
made this file jokes, data j s, and it's just an array variable that I'm exporting. And
that way in a component, if we want it, we can pull that in and pretend like that's us
getting data from an API. So how am I going to take an array of raw data and turn that
into a number of components? Well, there's a common saying for those that are learning
react, where they say that react helps them become better JavaScript developers. And the
reason is, because things like this are oftentimes handled by methods and kind of magic under
the hood for other frameworks like Angular or view. But in react, a lot of these simple
operations are handled just with vanilla JavaScript.
Let me show you what I mean. With a quick
aside, we're going to talk about some higher order array methods. If you're not familiar
with these, these are methods that you can run on an array that take a function as a
parameter and allow you the developer to decide exactly what should happen to the elements
in that array. For example, if I had the following array, I can run a higher order method on
nums. All map, and map is a method of the nums array, and
it takes a function as its parameter, this function will receive each individual number
in the array.
So I might say num or number, Tim, this function will then run on every
single item in the array. And with map, whatever I return from my inner function here, will
be placed in the same index of a brand new array with some kind of modification, meaning
map actually returns a brand new array, so I'm going to save a new array called maybe
doubled. Now, if I from my inner function, return, num times two, doubled should be an
array of 2468 1012, and so on, let's take a look.
And there's my array of all the double
numbers. If you're not familiar with higher order methods, they're one of the key components
of functional programming in JavaScript, and they're really, really awesome, I'd highly
recommend go study up a little bit on map, and filter and reduce, and some of the other
ones that are really useful. With this, we're gonna stick with map and we're gonna see what
we can use it for. So the first thing I'm going to do is pull in my jokes data importing.
And then we're going to follow the same pattern that we did in our example here, I'm going
to say, oops, data dot map, provide a function.
Now before I typed the longhand function,
so that it was a little clear what I was doing, but we're going to use an arrow function,
which can just as legitimately be used here, function is going to receive each individual
joke object, so I'll call it joke. And with arrow functions, if I just have one parameter,
I can get rid of my parentheses. And what I'm going to return from this inner function
isn't some modification on the joke objects per se, but rather, I'm going to return a
component joke component and pass in the data from the individual joke object that I'm looking
at. Because I'm only returning a single component, I can actually just do this on one line if
I want.
And if you're familiar with arrow functions, there's an implicit return so I
could actually get rid of some of that extra stuff. If this is confusing at all, then feel
free to put the return in there. It looks like I have an extra space there. And remember,
map returns A new array. So I'm gonna save that in variable. And now I have an array
of components. So what am I going to do with an array of components? Well, React makes
it really nice, where I can just put an array of components directly here in my JSX.
And
if I refresh this, you'll notice a couple things. First of all, my jokes on the right
are working again, just like they should be. And second of all, you might have noticed
this little error that popped up that says each child in an array or iterator should
have a key Prop, we won't go too much into the details of why react expects a key prop
on repeated components. But it's enough to know that whenever you're doing a map like
this, you should give the component that you're creating over and over a new prop called key.
Now, whether you're putting this on a component that you've created, or some kind of div that
you're surrounding it with, doesn't really matter. Just give it a key prop and put something
unique inside the key prop.
Usually data from an API will include some kind of ID number
or something else that's unique about it. As long as it's unique, it should be fine.
Here, I could use the question because the questions are all unique. But I've also included
for the sake of mimicking real data, some ID numbers that I might decide to use instead
for my key.
So over in app j, s, key is going to be choke.id. Now when I refresh, my warning
goes away, my app js is much cleaner than it used to be, my data is coming from somewhere
external, like it would in the real world. One of the main takeaways, though, is that
we're just using the built in JavaScript map method on arrays. In fact, I'm going to include
some links to the MDN docs on these methods that will be really helpful for you to understand,
if you don't already feel comfortable with them, you can see on the far right in the last part
of the URL exactly which method it is that this URL is going to be talking about in this
course, will mostly be using map, but we may throw in one of these other ones every now
and then you don't necessarily have to go memorize these perfectly right now.
But this
is just some more material that you'll definitely be interested in learning about. Something
else that I just thought of that may be really helpful to you is to realize that things that
we're teaching here, because so much of react is just vanilla JavaScript, you can use these
things as tools to do a lot of what your imagination could come up with. For example, as I'm iterating
over a joke component and creating a number of jokes, I may find a reason to also put
a map inside of my joke component. And I end up with a loop inside of a loop, where each
joke component renders an array of its own components.
That's totally possible. And it's
as simple as putting another map inside of your joke component. One joke component gets
rendered, it renders a number of other components. The second joke component gets rendered, it
also renders a number of other components and so forth. Some of these other methods,
like sort, for example, may be used to put things in an order that you prefer, or something
like filter could only display certain elements of an array rather than the entire array.
If you want an extra challenge, try making it so that our array of joke components gets
filtered to only display those that have fewer than X number of characters in the question,
or maybe filtered to only include items that do have a question rather than those that
are just an answer.
This is pretty much everything we have to learn about map right now. So when
you feel pretty comfortable with this, go to the next lesson to practice it. Okay, so I know I told you, I wasn't going
to make you create the entire react app from scratch. But I didn't make it a whole lot
easier for you. I did put the basics in so it's rendering an app component. And the app
component is just rendering an empty div right now. And here we have the instructions for
this exercise. So given a list of products as an array, which will be the products data
that I'm importing from the file called visco products, you need to create first and then
render a product component. For each product in the list, you're going to have a chance
to practice creating your own functional component, passing props to it, and rendering the correct
things to display inside of that component as its receiving props.
And you'll also need
to practice using the map method on the products data. This array of data is just an array
of silly objects that I created for a presentation that I gave last week here in Salt Lake City.
And each object has an ID, a name, a price and a description. You won't necessarily need
to display the ID as text on the page, but try to think of what this ID might be helpful
for. So I will go back to the app and I'll give you a chance to give this a shot. Good
luck. Okay, let's start with just a really basic product component. So I'm going to create
a new file and call it product dot j s Which I'll need to import react from react and export
product. It my functional component already know this is going to need to receive
products.
So I'll put props there. And let's just return some really basic JSX. For now
we'll wrap everything in a div. I have, let's say an h2. For the props dot product dot name. Now this is a
nested object because I anticipate passing the entire product down as one object rather
than passing down each individual property of the product individually as a prop. Instead,
I'll just pass the whole product down as one object and access the properties through props
dot product, dot and then the name of the property.
Down below it, I will put a paragraph
put $1 sign in front of props dot product, price. And then one thing I'm actually going
to put here is a string method called to locale string, which allows me to display this as
currency. And I believe if I do that, it will automatically put the dollar sign there for
me. So I'm actually going to take my dollar sign out. And then after that gets evaluated,
I might do like a dash and put the description. This is pretty boring. But I'd spend some
time if I were you styling this and getting some more practice with styling. So over in
app j s, I know that I'm going to be rendering a number of product components. So I need
to first import my product component file. And at the top of my functional component
here, I'm going to create a new variable called products. That's a product components. That's
going to be coming from products data dot map. So products data dot map, again, we'll
create a new array, and we're going to make sure that array is filled with product components.
So this will receive an individual product or item.
Maybe I'll say item just to distinguish
it from all the other things I have named product. I want this to return a product component where the product is my item. And now that I have this
array of product components, I'm going to put it inside of my div here and try refreshing.
Cool. One thing you notice is I got that warning about the key prop over here, I will also
add a key property. And I'm going to pass in the items Id just to allow it to have something
unique so that react can correctly place everything the way that it wants to. And I need to fix
my spelling here. Let's try refreshing again, everything is showing up correctly on the
right, and I no longer have that warning popping up, which is great. I'm a bit of a stickler
for correct indentation, so I'm going to fix by indentation here. And this essentially
is the completion of this exercise. Take some time to try and style this, see if you can
display things a little bit differently. Play with adding products to the visco products
array and see how that affects our website.
One thing I didn't show is that I can scroll
down here and see all of the other products that are listed in that array. Maybe try building
a button that when it's clicked in each product tops up an alert with the information about
that individual product to spend some time with this. And once you're ready, we're going
to talk about conditional rendering. Let's use what we just learned about mapping
and props to make our to do list a little more dynamic. What I've done is I've created
a to dues data js file here and all it is doing is exporting an array of objects each
object representing a to do item.
Now normally, you wouldn't do it this way, you would get
this data from an API of some sort where the data is living in a database. But since we
haven't really gotten there, this will do for now. Then over in app j s, I've imported
that data as an array called to dues data. So your task is to essentially turn this array
of objects into an array of to do items. Now remember right now to do items are hard coded
with what they're displaying. So that will also need to change. Go ahead and pause the
lesson and give this a try. So the first thing I'm going to do is take
my array and turn it into an array of to do items, then we'll have to fix to do items
so that it can receive props before my return.
We're going to create up An array called to
do items, which is the result of doing to dues data dot map, which will pass a function
to that receives an item. Essentially, we're just going to create a to do item. And we're
going to pass the information from the individual item object down to to do item currently to
do item doesn't accept anything, but we'll fix that in a minute.
So I'm going to pass
a prop called item. And its value is going to be the object. And
now that I have an array of to do item components, let's take these out and replace it with my array of to do items.
Okay, and you'll notice that I forgot to put a key prop in here, always an important thing to do. And
with the two dues data, what I've done is added an ID property, these IDs we can assume
will always be unique. And so over in app j s, I will just add a key. Let's say it's
item that I be rid of that warning. Now notice that I still have placeholder text here. But
now I have it five times. And that's because I have five items in my to dues data. But
to do items still has placeholder text here hard coded in it.
Well, we're passing an item
prop down. So let's go over to to do item, have it accept props. Instead of putting placeholder
text here, we will simply say props dot item dot txt, dot txt, because that's what the
property is called in my object. So I save this. And there we go. We have our to do item
showing up. And essentially, we're declaratively turning an array of raw data into elements
on our application. Now, it's actually going to be quite a while in this course, until
we learn about forms and learn a little bit more about how this input type checkbox works.
But what I can do is give you a little hint as to how to make it so that the checkbox
is checked, when the item is considered completed.
Over in the data, you may have noticed that
I've set a couple of these to complete and true. Let's make it so the checkbox actually
gets checked. When that happens. Again, we're going to cover this quite a ways down the
road. But just so you know, for now, every type checkbox gets a property called checked.
And essentially, it tells the checkbox whether or not it should be checked, if the thing
inside is true.
And it will be checked. And if not, it won't be checked. This is going to throw a little warning that
basically says you've added a checked property, but you can't change it ever. So it doesn't
have an on change handler. But for now, that's okay. We'll cover this again in the future.
But you can see in my window over here, take out the trash and mow the lawn are already
considered completed. And you'll see when I tried to uncheck it, it won't let me like
I said, we'll fix that in the future.
But this is kind of a cool little addition we
can make now, hopefully that wasn't too difficult. If it was feel free once again, go back, rewatch
everything, catch up on any of the lessons that you may have struggled a little bit through
up until now. And once you ready, let's go forward. If any of you have done a react tutorial
before this one, you might be curious why we're using functional components instead
of a class based component. When I'm teaching react, I prefer to start with functional components
simply because functions are really easy to understand. And it's obvious what we're doing,
we are simply creating a component with a function that returns the UI that we want
to show up on the page. But as we go deeper and deeper into react and start learning about
some new parts of react, we're going to find that a functional component can't do everything
that we need it to do.
And so at this point, what we're going to do is actually learn to
create a class based component. For now our class based component is going to do exactly
what our functional component does. And then in upcoming lessons, we're going to talk about
what class based components can do for us, such as allowing us to implement state and
lifecycle methods. But for now, let's just look at converting a functional component
into a class based component. If you're not really familiar yet with the class syntax
in e6, then I'd recommend going over to the scrim by six course and learning a little
bit about classes. So instead of converting this functional component to a class component,
I'm actually just going to create a new app class below it. And that way, we can kind
of compare the two. The class base component will always start with the class keyword.
And we're going to give it the same name of the component as we had before app tip instead
of parentheses and curly braces, we're going to extend react component and if you're not
familiar With classes or what this is doing under the hood, essentially, this is still
using a prototype system in JavaScript.
And it's setting up a prototype with react component,
all that really means is that we're getting a bunch of goodies from react component that
are pre written for us. And we're gonna get a chance to see that in upcoming lessons.
For now, I'm just going to open this with a set of curly braces. And every class based
component at least needs one method, and that is the render method, and it actually needs
to be spelled exactly this way. And then render will return exactly what we have in our functional
component. In this class component is identical to the functional component we had above.
So I should be able to comment this functional component out and save to watch the browser
refresh. And we have exactly what we had before. Now let's take a look at our render method.
Anytime we have any kind of display logic, that's going to happen, I prefer to do it
inside of my render method before the return. For example, you might remember a few videos
back where we created a date object. And then we use that data to determine what time of
the day it was.
And we displayed in the text and used some styling, and all sorts of stuff
like that. If you have any code that determines the display logic, or in other words, what
exactly is going to show up on the page or what the style of that element will be things
like that can go right here inside of the render method before you do the return. So
this is a good place to set up your style objects. If you're doing any inline styling,
running the logic that will determine how something will get displayed on the screen,
things like conditional rendering, all of that can happen here inside of the render
method. Now, if you're familiar with classes, you technically could also take that and put
it inside of a method of your own a class method.
To do that, above render, you would
just enter your own method right here. inside of this method, you can do any kind of display
logic that you wish. And then from inside the render method, you can call your method
by using this dot and then the name of your method. If your method returns something,
this is where you put that a few lessons in the future.
We're going to talk about some
caveats with this. But for now, it's just as easy to put your display logic here inside
of the render method. There's one other thing that we have to touch
on before we're done with this. And that has to do with props. In our functional component,
we could pass props to the function itself, then inside of our code, we would just say
props dot, whatever the property was on the props object, there's only one small change
we have to make with the class base component.
And that's that anytime we use props, we need
to make sure that we are using this dot props. It's a pretty common thing to forget to do,
especially when you're converting from a functional component to a class based component. But
it's also a bug that you'll get really good at catching and being able to fix right away.
And before this becomes confusing, I realized I forgot my curly braces up here. And to be
consistent, we will add a dot whatever here. As I mentioned at the beginning, class base
components enable us to do a lot of really cool new things with react, we're going to
be covering those over the next few lessons. But for now, let's get a chance to practice
this.
So take a second to play with this code. And once you're ready, let's move on to the
practice in the next lesson. You can see that I've set this up where I
just put all three of these components in the same file. And as I mentioned before,
you obviously would want to put these in separate files normally. But for the sake of practice,
we're just going to keep them here so you can see everything at once.
And as you can
see in the challenge, all you have to do is convert all three of these functional components
to be class based components. And also there's a small bug inside of this program. So see
if you can find it. So now's the time, pause the video and give this a shot. Okay, hopefully this wasn't too difficult.
All we're going to do is every time it says function, and then the component name, we're
going to change that to class. We need to extend react component, get rid of our curly
braces. And then instead of having a bare return here, we need that to be inside of
a method called render. And take this return type here, fix my spacing. And that's it for
the first one. The second one is essentially the same thing except now we have props and
we have to remember exactly what we're going to do when we have props. So Then function
will become class will extend react component and get rid of the parentheses, put my return
inside of a method called render.
And then the one thing that's always really easy to
miss here is that instead of props, it needs to be this dot props. Because this is a class
based component. This third component looks a little bit more complex. But essentially,
it's the same thing. Class greeting. And, and now, like I showed you in the previous
lesson, we could decide just to put component here, which then means at the top, we would
need to import react and component, then all of this logic is also going to go inside of the render method. Looks like this component is not using props
anywhere, so I don't need to worry about changing that to this dot props. And you can see I
still am getting exactly what I had at the beginning.
Now hopefully, you'll also notice
that there's a bug here, it says welcome, comma, and then a space with nothing in it.
If you didn't do this in the beginning, take a second now to try and figure out why that
is. Well, let's look at the component that's in charge of actually displaying this. And
that's our header. Here, we notice that it's saying welcome, this stop props, that username.
But when I am creating an instance of header, I'm not passing it any props. So it's coming
in as undefined. So it's coming in with nothing. And I need to actually pass something there.
So the prop I'm going to add is username was then we can put whatever we want here. There we go.
That's fixed. Hopefully, this wasn't too difficult of a
challenge. If it was then go back through it and try to convert these classes back into
functions. And then from functions back into classes. I know that sounds pretty tedious.
But honestly, it's one of the better ways to learn. Once you're ready, let's move on.
Okay, so we finally come to one of the most important parts of react and that is understanding
state. State is simply the data that a component maintains. And when I say maintains I mean,
it actually can change its value. The reason that's a distinct feature over anything we've
learned so far is because props, the other way to pass data from a component to another
component cannot be changed by the component receiving the props. They say in the React
documentation that props are immutable or unchangeable. All that means is that I can't
receive a prop and then say this dot props dot something equals some new value.
Okay,
I can't change props. And if I do, it may cause some weirdness with react. So state
is different in that it's a way that a component can maintain its own data and change its own
data if it needs to. Let me get rid of this before it becomes confusing, because you should
not do this. So anytime we're going to introduce state to a component. The first thing is that
the component needs to be a class based component. We'll talk a little bit in the future why.
But for now, just know that if you want state in a component, or if you want a component
to maintain its own data using state, it will need to be a class based component.
The first
thing we'll do to introduce state to this component is we need to add a constructor
method. constructor is a specific method that's built into JavaScript that initializes parts
of this class, if you're feeling a little unfamiliar with classes, I went and grabbed
the link to a screencast that has some information on classes that you're welcome to pause and
go look at really quick. But the important thing to know is that when you have a constructor,
it's a place where you're going to be initializing some values. And the first thing you should
always do inside of a constructor is make a call to a global function called Super.
In short, what super does is it goes to the parent class or what's also called the superclass,
and it grabs some of the goodies there and brings them down so that our class or our
app component can use those goodies.
One of the main parts of react component that we'll
be using is a method called set state. And that allows us to change state but we're going
to get there. For now just know that if you have a constructor, you should always add
super. And then the only other thing we need to do to add state to this component is to
add a property to this called state.
And state will always be an object. And so I'm going
to set the start state equal to an object. And now I have state in my component. I can
access this state anywhere else my components code by referencing this dot state Now you'll
notice that I have an h1 here that says is state important to know. So I'm going to add
a property to my state as an initial value, the property will be called answer. And its
value will be yes. Now take a second to think how you might get that value to show up inside
the h1 after this question mark right here. Pause the video and see if you can get that
to work. The first thing I'll need to do is add some curly braces, because I'm going to
be interpreting some JavaScript inside of JSX.
And then I simply type this dot state
answer. When I refresh the page, you'll see that it
shows up on my browser window over to the right, yes, here, what I'm doing is I'm giving
an initial value to my state. This is the data my component will have when it's first
initialized. And the special thing about state is that I can always change this to something
else later if I want. The only other thing I want to touch on in this lesson before we
move on is to mention that we can pass state from this component down to a child component.
And remember, the only way we can pass information from one component to another is through props.
And so that might look something like this, where I have some kind of child component
right here. And of course, if I want to pass any information down to it, it needs to happen
through props. So maybe I have a prop that I add called answer.
And its value is this
dot State DOT answer. The only other thing I want to mention in this lesson for now is
that react will do some really cool stuff if we ever change state. And I don't mean
changing it here manually in the initial value. But I mean, when we use the set state method
that I mentioned, which we'll talk about in a couple of lessons, but if we ever use that
method and change the state, React will automatically update every child component that is receiving
parts of that state.
And so changing the state will automatically change how things get displayed
on the screen. But we'll cover that a little more in depth when we start talking about
changing state. Now take a look at this code and try playing with state a little bit. And
we'll move on to a quick practice. Okay, so here's your challenge. And this is
actually a challenge that incorporates a little bit of debugging, not just talking about state
specifically. So you're given an incomplete class based component that doesn't have a
constructor.
And your job is to essentially initialize state and make sure that the component
gets fixed. Pay attention to the console, which I've opened in the bottom. So make sure
you look at that. And that should give you some good hints as to what's wrong. And for
the values of state, you should be able to figure those out based on the context of this
component. So go ahead, give this a shot. And we will do this together in just a few
seconds. Okay, so there's a lot to be done here. And
I'm going to start first by adding a method that this return can be inside. It looks kind
of like this was a functional component, and was changed haphazardly to a class based component
but in completely.
So the first thing I'm going to do is add a render method that this
return live inside. Okay, so when I refresh this, you'll see it says component is not
defined, well, that's a pretty helpful hint. We either need to extend react component,
or we need to import component from react. If we do it this way, then I can actually
keep it as component either way is totally legitimate. The next area we're going to run
into is a little bit tricky. So I'm going to save this. Notice it says cannot set property
props of undefined. Well, that's pretty confusing, because we're not actually using props anywhere
here. And where this comes from is this little set of parentheses that shouldn't be there.
That's how a function is defined, but not a class. So I'm going to get rid of those
and save it again. You'll see cannot read property name of No, well, here's name, and
it's seeing that this state is no. So as the instructions say I'm going to create a constructor
method. And the first thing we should always do in a constructor method is add super.
I'm
going to initialize my state is an object. And I can see from the render method that
that object should have a name property and an age property. So inside this object, I
will add a name property and we'll say le age of saving again, now have a functioning
component. There's no errors in the console and Sally and 13 years old are showing Have
correctly over in the browser.
Now one thing we've been talking a lot about at visco, which
is the coding boot camp that I work for, is how important repetition is. And I know I've
tried to get you to write this code over and over again. But I'd highly recommend that
if any part of this was confusing at all, that you go back to the beginning of the screencast.
And you pause the video immediately, and you try to fix it yourself again. And then after
you do that, do it again, go back to the beginning, try and fix it again from scratch, and do
it again, and do that as many times as it takes for the syntax to kind of be second
nature for you. Doing that is going to do a number of things. But mainly, it's going
to make it so that in the future, you don't get so hung up on figuring out and remembering
the syntax as much as figuring out how to solve specific problems.
So feel free to stop
here, go back, redo this as many times as is necessary. And then when you're ready,
feel free to move on. Okay, so I actually decided at the last second
that I wanted to add another practice in here. And this practice is going to do two things,
it's going to give you the chance to practice converting a functional stateless component
to a class based component. Again, it's also going to give you a chance to add state to
a component. And then I have kind of an additional challenge here, that covers something we haven't
quite talked about yet, which is conditional rendering. But I want you to just give it
a shot, use your intuition. And if you're wanting to do any kind of Google search, you're
welcome to do that, too. And we are going to cover this soon. But I figured this would
be a good chance for you to exercise your problem solving skills. So given the component
here, change it to a stateful class based component, give the state a property called
is logged in, which should be a Boolean, either true or false.
And that's the first part.
If you can do that, that's awesome. Then I want you to give it a shot at rendering the
word in if the state is logged in is true, or the word out if it's false. So go ahead
give this a try. Okay, so the first part, we should be able
to do relatively easily, we need to change our functional component to a class based
component. So I will add class here, going to get rid of my parentheses, add extends
react dot component, I return needs to be returning inside of a method of some sort.
So I'm going to add my render method, my return inside game, then if I'm going to add state
to it, I will need to make sure I have a constructor which calls super.
I add a property called
state on this, this that state equals an object. We know that object needs to have a property
called is plugged in. We will initialize it as true. You were able to get to this part,
that's awesome, great job. The next thing is making it so that it renders the word in
here if is logged in is true or out if it's not. And again, we're going to cover this
when we talk about conditional rendering in a few lessons. But one way that we may decide
to do this is to maintain a variable that looks at the current version of is logged
in, and has a string that represents the word that should be displayed here.
That display
logic, as I've mentioned, I like to do inside my render method but above my return. And
so I'm going to maybe initialize a variable called Word display. And do a simple if else
statement that says if this start state that is logged in, is true. We're display should
be the word in otherwise, or display should be out. Finally down here, instead of having
both in and out here, I'll put curly braces because I'm interpreting JavaScript inside
of my JSX. I will simply put word display, I noticed that word display is just a local
variable to the render method, I don't need to put this dot State DOT word display or
this dot props that were displayed because it is neither a prop nor a piece of state.
Now when I refresh this, I get you're currently logged in.
And that happens because is logged
in is true. And if I change this to false, tell me I'm logged out. We're gonna see more concise ways to actually do
this is a totally legitimate way. And in fact, I believe this is the way that the React docs
tell you to do this. One thing I like to do if my variable is clearly named to be a Boolean,
like is logged in, I'm just going to get rid of my triple equals true because that will
already either be true or false. And that's it. So once again, please go back, try to
redo this yourself. See if you can do it from scratch, even delete the entire file and see
if you can write everything from scratch once again. Repetition is really going to help
you get the syntax down muscle memory so that you can focus more on problem solving.
Once
you feel pretty good about this, let's go forward. We are at part four of our to do app. So this
should be a pretty short one. Until now all we've done this loaded our to dues data into
our app component by importing it and then mapping directly over the thing that we imported.
However, eventually, we're going to want to modify this data, which means that it's going
to have to live in state of this component. So all you need to do for this challenge is
to make it essentially so that two dues data lives in the state of this app component.
Pause the lesson here and give that a try. Okay, like I said, to dues data is just imported.
And we originally were mapping directly over the thing that we imported. But let's put
this on state. for that to work, I need this to be a class based component. That will extend
react component.
Parentheses, we need a constructor always calls super first. And we'll start
some state, which is an object and we'll have maybe just to use is an array, we'll start
as an empty array. And that in just a second, right now, this map and the return need to
happen inside of a render method, we'll just move that in there. And then like the challenge
says, We essentially want to load the imported two dues data into state, which essentially
just means that instead of an empty array here, we will put to dues data, then the last
thing is to change to dues data to this dot State DOT two dues, because that's where the
two dues data is living now. I believe if we refresh, we're working great. The warning
that we receive is from the previous lesson where we had the checked property, and we
don't have an on change. But we're going to get to that later when we talk about forms.
For now, this is heading in a good direction.
We will revisit this in a little bit. But
until then, let's learn some more react. Before we can seriously talk about changing
state using the set state method, we're going to need to have an understanding of events
in react and handling events. event handling is essentially allowing the user to interact
with your web page and do something specific when a certain event like a click or hover
happens. And handling events in react is actually quite simple. You might be familiar with regular
HTML is the ability to add something like on click equals and then you execute a function
like my function. React is very similar to this with just a few small changes. The first
thing is that all of our event handlers are going to be the JavaScript version, which
has a camel case convention on click will have a capital C, on mouse over will have
a capital M and a capital O and so forth. And the reason it does this is because it
uses the same convention that regular JavaScript as if you were to add these events to elements
on the page.
So let's make it so our button can do something when a click of the button
happens using onClick. And then the only other major change we're going to do is that instead
of passing an executed function as a string, we're going to pass a function directly into
a set of curly braces. I don't have another function pre written so I could just do an
anonymous function right here. And maybe console log something. We can shorten this up quite
a bit by using yes sixes arrow function syntax. Or as always, you could write a separate function
somewhere. And put the reference to the name of that function right here. Any of those
should work just fine. I'm going to save this and click the button. And you'll see that
we get a console log of I was clicked. If we open the console, we will see that more
obviously. As a quick reference, I want you to take a look at the following react documentation.
This is a full list of the supported events in react.
The reason I want you to look at
this is because I want you to pause this lesson and add the functionality so that when the
mouse hovers over the image, another thing gets console log. So pause lesson here, feel
free to go to that URL and see if you can find the event that we'll need to use so that
when we move our mouse over the image, it will execute a function And then go ahead
and add that to your image element. Okay, so I think there might be a couple different
mouse events that we could use. But the one that I'm going to use is the on mouse over.
And when that happens, we will run the following function. And we will just console log, Hubbard
save this. And I'll open the console and try hovering over Bill Murray. Like that. Every
time our mouse goes over the image, it runs our function to handling events is going to
be really helpful. Obviously, console logging stuff is not all that exciting. But we're
gonna see how events mixed with the changing of state will allow our application to start
becoming really robust and actually really awesome.
Feel free to add a few elements here,
see if you can do some of the other events that are found at this URL. And then we'll
talk about setting state in the next lesson. So we another really quick update to our to
do app, we just learned about how to add event handlers to elements. And you may remember
that we used to have a warning, saying that we have checked prop on our input. But we
don't have any way to change that. So it says it will render a read only field. So your
challenge is to get rid of this warning by simply adding an on change to our input. And
for now it can just console log something. So pause now and give that a try. I'm going
to close this console for some extra room. And this simply entails adding an on change
that is equal to and then I could write this function somewhere else.
Or I'll just do an
anonymous inline function that until logs. While I'm at it, I'll put these on their own
lines. And now when I click these, it doesn't change the checkbox. But our warning is gone. And my onchange is
firing correctly. So we're going to learn about how to make these events actually change
our state. And then we'll be revisiting this app again soon. Okay, man, every new lesson just feels so
exciting because you're learning something that's like really bringing you close to making
awesome web applications with react. In this lesson, we're talking about changing state,
okay, having state in your component is great. But if you can only initialize it to a specific
value and can't change it, then frankly, it's kind of pointless to be there.
And it's really
no better than just hard coding it into your code. So let's learn about changing state.
And what we have here is a component that is a class based component. Because we're
using state, we have our constructor, we're calling super, as always, we're initializing
state with a property called count, and setting that equal to zero. And then in our render,
we simply have an h1 that displays the current count. And we have a button with the word
change in it. I've added a little bit of CSS, so it wasn't quite so ugly. And now we're
going to learn about how when I click this button, using the event handlers that we just
learned about how can I change the state to be something different, so that clicking the
button will actually change the value that gets displayed here? Well, let's start by
adding an event handler, which should be reviewed from the last lesson. So go ahead and see
if you can make it so that when you click a button, maybe something gets logged to the
console.
For now. Remember, to add an event handler I'm going to do on click in this case,
because I want it to handle the click event equals and then inside of curly braces, I'm
going to put some kind of JavaScript function. Now I could put an inline function right here,
which I don't particularly like. So instead, what I'm going to do is I'm now going to create
my own method constructor is a method that's built in to classes in JavaScript.
Render
is a reserved method name for react. But in between here, I can put as many methods as
I want. One strong convention that people tend to use is to have a method called handle
click when you're handling a click event. So I'll finish the stubbed out version of
this and then down here, instead of an inline anonymous function, I'll have it run handle
click.
Now let's see if I can get a console log to show up. Let's save that. And this
is a common mistake. When the method is part of my class, I need to reference it on the
this object. So this dot handle click to begin, click my button and says I'm working. Okay,
that worked. Well, that's pretty boring. So let's make it so that when I click it, actually
changes my state and increases my count. Now one thing that would be really tempting to
do is to try and modify state directly, as in typing this dot State DOT count equals
one, or saying something like plus plus, or this is something that you will actually never
do, you're never going to want to directly modify the original version of state. You
might remember in the introduction to state, I talked about how state is kind of like the
clothing that you wear. Well, when it comes time to change your clothing, you don't modify
your clothing, right, you don't paint your clothing a different color, you don't cut
a T shirt, and so on buttons, so that you can have a button up shirt instead.
But what
you do is you completely replace your old clothes with your new clothes, or rather the
clothes you were wearing with the clothes that you want to wear. And this is essentially
the same thing we're going to do with state. You also might remember that I talked about
some kind of goodies that we're going to get from react component. And that's the reason
we're extending react component. Well, one of the things that we're going to get is a
method called set state.
And anytime you want to change state, you're going to use this
method set state. And it's a method or function, so I'm going to call it and there's actually
two different things that you can pass to set state. Let's first look at the easier
one to understand. What I can pass to set state is a new version of state, while state
is just an object as we see up here. So I can pass to set state an object, and I can
say, the count. Now, one might have already figured out what's
going to be the problem with this. But let's see if this works. So once again, my button
has an unclick, that will run this dot handle click when it's click, this dot handle click
uses the set state method that comes from react component. And it provides a new version
of state, okay, like your new t shirt that you're putting on. And it says now the count
should be one, I'll click the button. And we run into a very common error says, cannot
read property set state of undefined.
This brings us into a realm that's actually kind
of hotly debated with react. And I'm going to give you a very simple solution to this,
that may not make a whole lot of sense at first. Essentially, anytime you create a class
method that you want to use set state on, you're going to need to bind this method to
your own class. If you're not really familiar with binding, I'm not too worried about that
right now, just know that anytime you write a method that uses a set state, you'll want
to bind it and the way you bind it is inside of your constructor, we're going to say this
dot handle click equals this dot handle click dot bind this, like I said, this is probably
pretty confusing if you're not familiar with binding.
But essentially, what it does is
it makes sure that the handle click method is bound to the context of this as it exists
within this class. I'm going to refresh this and click my Change button again. And awesome.
Look, our state changed from zero to one. Now this is where the problem that you may
have figured out already comes into play. If I click Change, again, it looks like nothing's
happening. But in fact, it's actually doing what I told it to do, right? When I click
the Change button, it sets the state to the count. And the count is now one. Well, it
was already one and I'm changing it to one. So it's actually not changing. Therefore,
I can't see it changing on the display. So that brings us to the second way that I could
use set state, if I don't care about what the previous version of state was.
Passing
in an object is a really nice simple way to provide a new state. But a lot of times we
actually do care what the previous state used to be. In this case, we want to know what
the previous state was. And we want to add one to it. So anytime I need to know what
the previous state was, I can also pass a function to set state that function is going
to receive in its parameter, the previous version of state. This is really important.
And it might be tempting to think that you can just access the previous version of state
using this dot state, which sometimes will work but oftentimes will not. And so it's
really important to always pass previous state or whatever variable name, you want to give
this to your function.
Now because it's an arrow function that just has one parameter,
I can get rid of my parentheses around that parameter. And what my function should return
is a new version of state. Okay, so before we provided just a new version of state directly
as an object literal, but this time we're providing a function that returns that object
literal. The benefit of doing it this way is we have access to the previous version
of state. So in my function, I'm going to return an object, that object should have
a count property, so that I don't break my this dot state count down here. And I want
you to take a second and see if you can figure out what the value of that property should
be. So positive lesson and give that a try. So remember, previous state represents the
old version of state. And the old version of state is an object. So I can access the
previous version of state by saying proof state. But that's the whole object, I just
want to count property. And I'm not going to say plus plus, because that's directly
modifying the old version of state.
But instead, I'm going to just add one to it, we computer
will do is it will figure out what the count used to be, they will add one to that. And
it will set that as the new count property of my new state object that's getting returned
from this function. Now, when I save this, and refresh, and I click Change, I can click
it multiple times. And it will continue to increase the number that's displayed on the
screen. And this is really cool. I mean, it seems kind of lame, because all I'm doing
is increasing a number. But this opens up so many possibilities. And you're going to
see from here on just how much we're going to be able to do with react. Now that we have
the ability to have components, maintain their own data and state and actually change their
own data using set state. I mentioned before that you are allowed to pass state down to
other components as props, for example, having a child component of some kind that receives,
you know, your account, your state. And if we were to define this child component, we
would see that it's receiving a prop called count, the value of which is the current state
of its parent component app.
Well, what react will do is anytime this value changes, anytime
it sees that there's a child component that's receiving a value that changes, it will rerender.
This component, it will run that components render method, once again, or if this is a
functional component, it will just run that function again, so that that component can
reflect the new version of props that it's receiving.
And in this case, it will change
every time the state count changes on the app component, which as we just made it do
happens every time we click the Change button. So right now child component isn't actually
defined. So I'm going to get rid of that before I get a syntax here. And let's do a quick
recap of everything we did. We have our h1 displaying our state, which just has a count
property, we initialize that count property to zero, we added an event handler to our
button that runs a method called handle click handle click is a method defined on this class.
And because handle click is using the set state method that comes from the parent class
react component, we need to make sure to bind it, which we can do inside of our constructor.
And once it's bound, we can run set state, which can either take an object literal, which
is the new version of state that we want to pass to it.
Or if we care about what the previous
state used to be, we'll pass it a function that takes the previous state as a parameter.
And that function should return the object literal that represents the new version of
state. Now I just rattled off a lot of jargony stuff. So I want you to spend some time with
this state is going to be extremely important for you to understand. And we're going to
be using it pretty much through the rest of the course, though spend some serious time
with this, I'd highly recommend as I have in the past tried deleting this entirely writing
it from scratch. And we're probably a good stepping stone to that is rewinding this video
to the beginning and seeing if you can add all of this stuff again, you're also welcome
to try adding different events that may also change state in play with the state that's
getting changed, maybe you want it to increase by more than one or something like that, I
don't know. One really good exercise is to have a button that will double the number
and another button that will have the number.
So there's plenty of things that you can try
to do with this. So use your creativity and your imagination, see what you can come up
with. But spend some real time with this and play with it. Then in the next lesson, we're
going to get a chance to practice this. Okay, we've come to a pretty beefy part of
our to do app, we're going to make it so that when we click the checkbox, it actually makes
a change to our state. And this actually is a little more involved than it may sound but
it's really not too bad. up near the top. I've written down what your challenge is and
This will help you accomplish this task. And I've also stubbed out the handle change method
and written some pseudocode inside here. So you have some hints, essentially to help you
accomplish this. And just so there aren't any weird bugs, I've also bound this in the
constructor for you. So your challenge is going to be to take this stubbed out, handle
change and actually implement it so that when somebody clicks the checkbox, it makes a change
to your state and updates the item that they checked so that the completed property flips
from either true to false or false to true.
And then you're going to make sure to pass
the handle change method down to your to do item. And then over in your to do item, you'll
need to implement the on change with the new method that you've passed to it. So I go back
here to app. Pause now and go ahead and get started. Okay, so I might do this a little
bit out of order. But I think the very first thing I'm going to do in my handle change
is just to console log something. Say we changed. And since we're getting the ID, let me just
go ahead and add the ID to my console logs, so I can make sure that that's working. And
then I think what I'll do is hook up parts two, or complete parts two, and three, and
just see if I can get this console log to happen. And then we'll go ahead and add this
logic. And so part two says that I need to pass the method down to the to do item components.
So right here, I have my to do item, which gets a key and the item.
And let's go ahead
and pass down a handle change was passed down this dot handle change. And then over into
do item, it's now receiving a prop called handle change. So props that handle change.
And notice that it says it's going to be taking the ID as a parameter. However, we know that
events when they fire, they actually receive an event property. And so it won't be good
enough to just say props dot handle change, because because this is not going to receive
an ID property, it's going to receive the event object instead.
And so what I can do
is say, Well, this is the function that's receiving the event here. And what it does
is it calls props dot handle change. And now I can pass whatever properties I want to this,
I want to say props.item.id. Since I'm not actually using this event, in this case, I'm
just going to get rid of that, it'll just be an empty function that calls props dot
handle change and passes the ID to it. So let me update my page. And we'll open the
console and just see if my console is working. Okay, change to change three, one, notice
that it's matching up with the ID of the item that I'm clicking. So this is ID of one ID
of two ID of three. And if I click the clean Gecko tank number three, it says Edit change.
Number three, awesome. So we've made some good headway there by finishing parts two
and three. But let's get to actually updating our state.
This is the trickier part. The
part that's tricky about this is that we need to deal with the entire array, because we're
saving an array in our state. And we never want to modify state directly, it won't be
as easy as just looping through this array, finding the item with this ID, and then flipping
it because that will actually modify the existing state. But instead, we can essentially do
that same thing. And just make sure that we return a brand new array where almost all
of the items are exactly as they used to be except one item has changed its completed
property from true to false or false to true. And a great way to do that is to use the dot
map method, because this returns a brand new array. And so what I can do is I'm going to
start my set state.
Because I do care what I have in my previous state, we're going to
use the function way of updating state and receive my previous state. And then what I'll
do is I will use map to loop over my proof state.to dues array and look for a to do with
the ID that is given here in the method. And so I'll create a variable that says maybe
updated to dues. That's going to be my old version of to dues.
And sorry, this shouldn't
be this that state but rather create State DOT map. And we're going to look at each one
of the two dues in this array. We'll run this function and we're
going to say if print to do that we're looking at has an ID that's equal to the ID we received
from our parameter up here. Then we know this is the to do item that we want to flip the
completed property of So I can say the to do dot completed, should equal the opposite
of whatever it currently is. And whether or not we actually did that flipping of the completed
property, we're going to return that to do that makes it so that it puts this to do item
in our new array in the same index have the original array.
And all of this is my map.
And so what my set state needs to do is actually return a new version of state, which is just
an object. And our state is an object with a to dues property. So I'll say to dues now
be the updated version of to dues, the array that we just created. Let me clean this up
a little bit, get rid of these comments, this, and let's try flipping these awesome. And
it looks like everything is working the way it should.
So as a recap, we are looking at
our previous state, and we're creating a new array that almost perfectly mirrors what it
used to be except one of the items, which has the same ID as this function received
from the on change handler that is happening when we click these checkboxes. That one item
is changing from true to false or false to true. And then this brand new array is essentially
replacing the old array that we had up here, and it gets rendered to the page. Then we're
taking this handle change method, and we're passing it down to every one of the to do
items that we create in our map down here.
And those to do items are receiving the handle
change. And anytime it's checkbox gets checked, it calls on change. And that has an anonymous
function, which then calls handle change and passes this items ID so that we can correctly
identify which in the array we need to flip. And as a reminder, the reason the checkbox
is actually showing up or not showing up is because of this checked property checked determines
whether the checkbox should be checked or not. And it says if the item is completed,
then it should be checked. And if the item is not completed, and it shouldn't be checked.
And essentially what we have now is a working to do app, we're going to do some small tweaks
to it. But great job.
Hopefully everything that we've covered so far makes sense. And
we'll be revisiting this soon to talk a little bit more about styling, but feel free to celebrate
a little bit and whenever you're ready, we'll go forward. One of the really nice things that we've mentioned
about react is how we get to essentially just write vanilla JavaScript. And react is taking
care of a lot of stuff behind the scenes, will with the stuff that's going on behind
the scenes, every single component that we create, is actually going to go through a
series of phases or milestones during its time being alive in your react application.
Often this is analogous to a human being who is born has life milestones, and dies. Similarly,
every react component will undergo a series of events when it's being rendered and updated.
Now I've divided lifecycle methods into two parts, because the React team has just recently
deprecated or gotten rid of three of the original lifecycle methods that we're about to talk
about.
And instead of going through every single one of these individually, I'm actually
mostly going to just talk about the ones that are the most important to you right now as
you're learning react. And then as you continue to learn, you can play with some of these
other ones as well. For for reference, I'm going to post here a URL to a site that does
a really good job explaining the lifecycle methods that were a part of react before version
16.3.
Check out those changes that happened in 16.3, you can check out this website, which
is the official blog of the React team. With that being said, let's start talking about
the lifecycle methods that were most likely or most commonly going to use. The first is
one that you're actually already familiar with. And it's a little bit of a gray area,
because this is oftentimes not listed as a lifecycle method. But the render method, right
here is something that we've been using, as we've talked about class based components.
And one analogy that I like to use is that it's like getting dressed for the day. Its
job is to determine exactly what gets rendered to the screen, which in turn is how the component
is displayed to the world. Now the render method can be called many times, anytime react
determines that something changes like state or props, which might affect how the component
is supposed to display, React may run the render method once again. Similarly, you may
have had days where you've decided to change your clothes and look a little bit different
to the world based upon what you're about to do.
So hopefully by now that one's pretty
straightforward. The next lifecycle method that I want to talk about is called component
did mount and these lifecycle methods are defined just like other methods inside of
your class. Here. So I might say component did Mount camelcase, like this component did
mount is a lifecycle method that's essentially like saying you were just born the component,
this component did just mount to the screen, the very first time the component shows up,
React will run the component did mount method.
This method will only run once while the component
is showing up on the screen. Things like a rerender, which changes the way that the component
is displayed does not rerun component did mount. And that's because the component doesn't
actually unmount and remount. Most common use case for component did mount is to do
things like an API call when you need to get data from some kind of external source. For
example, maybe this component is actually a to do list. And I need to get the list of
to dues from some kind of server or database. Before I'm able to accurately display my to
do list. As soon as the component finishes mounting, I can get the data I need to correctly
display. We're going to see this in a future lesson. But just know that that's one of the
most common use cases for component did mount.
The next lifecycle method I want to talk about
right now is called component will receive props component will receive props is kind of like
when someone gives you a gift. This component could be receiving props from a parent component.
And every time this component is receiving props, it will run this component will receive
props method, and component will receive props will not only run the very first time the
component is mounted. But it will also run every single time a parent component decides
to hand props to a child component. For example, if a parent component decides to change the
props that it's passing down to this component, one thing we can do inside of component will
receive props is check to see if the new incoming props are even different at all from the existing
props.
Oftentimes, we will then say if they are not different, just don't do anything.
But if they are different, maybe I have some kind of calculation to run or state to set
or something like that. To receive those new incoming props component will receive props
receives a parameter called next props. And it's just a parameter so you can call it whatever
you want. But oftentimes, we put next props. And sometimes you'll see something like an
if statement that says if next props dot whatever property you're looking at, does not equal
the existing props. Then do something important here. So there's some
good use cases for component will receive props. However, as I mentioned, this is actually
one of the lifecycle methods that's going to be deprecated, or actually is deprecated.
Starting in 16.3. Until react 17 comes out they've renamed this with all caps unsafe
underscore component will receive props.
So if you really need to use this, you can still
do so. But once react 17 comes out this is going to be completely removed in component
will receive props will no longer mean anything special. So just be aware of that. It's a
good lifecycle method to understand. If you're looking at legacy code. For going forward,
this won't be a part of react anymore. Another cool lifecycle method is called should component update. And in our person analogy, I like to think
of this as making a decision as to whether you need to change your clothes or not. Behind
the Scenes if react has any kind of question at all as to whether a component needs to
rerender it will always choose to rerender it just in case without any logic specific
to your applications needs behind that decision. I think I said in the past that sometimes
react will rerender a component even if nothing about that component has changed.
Well, that
can become kind of an expensive or rather slow operation. If you let that happen to
every single component in a large application. Should component update gives us the developer
a chance to optimize our app, we can implement some logic here that allows the component
to determine whether or not it's important for it to even think about updating. To help
make that decision. This is going to receive the incoming props and the incoming state,
which we'll call next props in next state. And in the body of the function we need to
either return true if we do want it to update or we can return false if we don't want it
to returning false Should component update is what will make your application more performant.
But you'll just want to make sure that you actually don't want this component to update.
Otherwise, it could really introduce some weird and hard to debug bugs into your code.
Less lifecycle method we'll talk about right now is component will unmount.
Just like in
life, all good things come to an end and your component will eventually unmount from the
screen or disappear altogether from the screen. The main use case for component will unmount
is to do some kind of cleanup or tear down of anything that you've set up, it could potentially
lead to clutter in the DOM or in your application. One of the most common use cases for this
is if you in component did mount set up like an event listener, for example, you wanted
to run some code every time somebody scrolled on the screen, this would be a chance to remove
the event listener, that that's just one example. In general, it's a place to tear down or clean
up your code before your component disappears. I'm going to move to this after that, so that
it's obvious. It's just an example. And that's actually all the lifecycle methods, we're
going to cover in part one here, there are a number of other ones that are important
to understand.
But for now, they're more advanced than what we're planning on getting into in
this course. And so I'd recommend if you're interested in learning more about them, going
up to this link up here. Now this link was written before 16.3 was announced. So also
take a look at the second link here, which will talk about the three lifecycle methods
that have been deprecated. As well as the two new lifecycle methods that are introduced
in their place, which we're going to cover in the next lesson.
You had a chance to go over this link here,
which is the announcement of react 16.3. And the changes that came with it, you will have
read about the three lifecycle methods that have been deprecated. One we talked about
already, this component will receive props, that's going away. A couple more lifecycle
methods that are also being removed our component will mount I'm just going to comment that
out right away, as well as component will update shall also comment out those three
component will mount component will receive props and component will update are being
deprecated or removed from react. In its place, we're receiving two new lifecycle methods
that we can use. One is called get derived state from props. Now there's one change about
get derived state from props. And that's that it's a static method. So we have to include
the word static beforehand, get derive state from props receives props in state and should
return the new updated state based upon the props. And I don't plan to go too much more
into this.
And the reason is because the React team has actually written a blog about how
you probably don't need derived state. A lot of times this has been misused and caused
weird bugs or performance issues in people's applications, when in reality, there's actually
a better way to go about what they were trying to do. The idea behind get derive state from
props is for like it says in the blog, the rare cases when your component needs to take
incoming props it's receiving from its parent, and set its own state based upon those props.
But again, the React team kind of discourages the use of this method. And so I'm not going
to talk too much about it. And we probably won't be using it in this course. However,
if you're interested in learning more about it, here's a link to the docs on get derive
state from props.
And the last lifecycle method, the new one that's being introduced is called
get snapshot before update. You can think of get snapshot before update as a lifecycle
method that allows you to sort of create a backup of the current way things are. When
I say backup really all you'll be saving is some kind of data of some sort, probably an
object with multiple points of data inside of it. And that object would be called the
snapshot because it's like a snapshot of the way your application is right now. Again,
the React team says that it's not a super common lifecycle method that you'll end up
using. And so we're not going to talk too much more about it. But once again, here's
the documentation if you're interested in learning more about it. So that's essentially
it for lifecycle methods for now, as you get more and more advanced in the applications
that you're building with react, you'll definitely want to become pretty familiar with these
lifecycle methods. For this course, we'll pretty much plan on sticking to component
did mount and render.
And if we end up meeting another one, then I'll make sure to talk more
about it at that time. Feel free to read through some of these articles. And when you're ready,
let's move on. You know, one of the hardest things about
teaching react is that you learn a number of tools that can be used in a variety of
ways. But you aren't necessarily constrained to just one way of using a tool. The other
thing is react uses so much vanilla JavaScript that a lot of what you can do with react is
done a number of different ways, using just vanilla JavaScript. Conditional rendering
is where this kind of comes into full view.
So I just wanted to start with that caveat,
before we get into this, because I don't want anyone to think that the way I'm about to
show you conditional rendering is the only way it can be done, I'm going to cover a number
of use cases, but there's for sure going to be other ways to use it that are totally legitimate.
So I've done here is I've added a class based component, it has state with a property called
is loading that is either true or false. This is something that's oftentimes used when you're
making a call to an API. And in the meantime, you want something to show up, perhaps that
call to the API will take three or four seconds.
And you don't want the user to think that
your website has crashed. And so you'll maintain something in state that says, hold on just
a second we're loading right now. And conditional rendering will be used to actually display
something on the screen that tells the user that you're currently loading something in
the background. We'll talk about component did mount in a second. But now in the render,
you'll see that we are rendering a component called conditional, which I'm importing up
above, and I'm passing a prop to it called is loading, which is the current version of
state. And then over and conditional, we're going to be adding what gets displayed on
the screen here for now. But before we get there, I want to be clear of what's happening
with our component did mount. Remember that component did mount is a chance for us to
run some code right after the component, our app component in this case mounts on the screen
for the very first time.
And what I'm doing here is kind of faking an API call, I've set
a timeout, which will wait one and a half seconds before running the code that's in
the function I provide it. And what's happening in that function is I'm changing the state.
So that loading is false. Think of this as a fake way to pretend that we're making a
call to an API that takes 1500 milliseconds, or one and a half seconds to come back with
data. At which point we're saying we are no longer loading because we finished loading
the data from the API. And once we talk about using fetch to get data in a future lesson,
we're actually going to be doing this for real, but I just wanted to make sure this
wasn't confusing before we move on. And actually, this is a good time to talk about the lifecycle
methods once again, because once set state changes is loading to false, our component
or conditional component, is now receiving a different Prop, because it's receiving is
loading of true when it first loads. And then when state changes and is loading as false.
It's receiving a new Prop, or rather, it's receiving the same is loading prop with a
different value.
And so what will happen is when the state changes, our render method
will run again, because something has changed, which means the conditional component will
also rerender. Now conditional is just a functional component, which means the function will just
run again. And whatever we're returning from here could potentially change because props
are going to be changing. When we get to the end of this lesson, I'll highly encourage
you to play with it because this is a really important topic.
Okay, so my conditional component
is receiving a prop called is loading. And before we get anywhere else, let's see if
our set state is working. I'm going to fix the syntax error by actually having something
render here. And I'm going to console log props.is loading. Notice that and I'll refresh
this again, notice that immediately, what happens is it shows up as true. And then 1500
milliseconds, or one and a half seconds later, it re console logs false.
And that's because
over an app, after 1500 milliseconds, it changes state to false, and that's when conditional
re renders or runs again, and the props that it's receiving changes. So first, it logs
true and then it locks false. Well, let's talk about conditional rendering. Essentially,
all that means is that I'm going to load something on the screen if a condition is true. In this
case, instead of an h1 that says temp. What I might do is say if upstart is loading is
true, then what I want this component to return is an h1 that says loading.
But if props that
is loading is not true or in other words, I can put that inside of an else once you to return
and have different text. And notice what happened when I refreshed, I'll do it again. At first
it says loading. And then it changes to the different h1 that we have here that says some
cool stuff about conditional rendering. The app component starts with is loading is true,
and therefore renders a conditional component where is loading prop is true.
And then the
conditional component checks if props that is loading is true. And first, it loads this
h1 or renders this h1, then when props.is loading changes to false because the state
of the parent component changed to false, the conditional component that we have here
runs once again and it notices that prompts that is loading is no longer true. And therefore
what it returns is this h1 instead, this is just using plain JavaScript. And if statements.
One thing that I personally prefer, because I'm returning from my function in my if statement
is I don't actually need my else here.
This will simplify my code a little bit. And this
return will only run if my if statement does not evaluate to true. And therefore it's kind
of an implied else. Well, this is a perfect time to talk about a common way to do this
kind of if else rendering using something called a ternary. operator. If you're not
familiar with turn Aires, this is not even a new feature in iOS six, this is something
that's been around for a while. And it's very commonly used in react applications. When
it comes to conditional rendering. Essentially, the way it works is you provide a condition
and then a question mark, you provide a statement if it's true, followed by a colon, and then
a statement. If it's false, in our case, our condition is, is props.is loading equal to true.
And then I like to read it like an English
sentence with the question mark props that is loading is true. If so then I want this
h1 otherwise, is what my colon means I want this h1. Well, I'm going to have a syntax
error here. And that's because when we're doing this inside of a component, we have
to do this inside of our return. So I'm going to delete what we have here, I'll delete my
comment, I'll add a return. put this inside of my return. Now, technically, this works.
If I refresh, you'll see it shows loading, and then some cool stuff about conditional
rendering. But this looks really strange to me as because we're not immediately returning
a parent JSX element, which we usually want to do.
So I'm going to wrap this whole thing
in a div. And then when I refresh, you're gonna see that there's another error we have
to fix. Notice that it's literally interpreting as text, the stuff that I shoved inside the
div. So if I want this to be interpreted as JavaScript, I need to wrap it in curly braces.
And now when I refresh, we're back to working. What's nice about this is that when I inevitably
have other things on my page, like some kind of navbar, which I'll represent with another
h1 here, maybe a footer, I can still be rendering conditionally parts of my page.
Another simplification
that I can make here is because is loading is already a Boolean, I technically don't
need the triple equals true, I can get rid of that. And this will test the truthiness
of props, that is loading, I'll refresh and you'll see it works the same. There we go.
Now, I put in this navbar, and footer as demonstration purposes, but I want to remind you, there's
so many different ways that you can structure this, that it's really hard to teach all of
them. For example, usually you won't have your navbar and your footer inside of a child
component of your app, these would likely go in your app component or somewhere similar.
That's a parent of this little conditional component.
And another thing is I've put this
conditional rendering here inside of the conditional component, just so we could see it all in
one place. But the truth is, our app component is probably the one that should be in charge
of the conditional rendering. The reason is whatever we put in our conditional component
should probably just be able to display when it's told to display it. If our app is in
charge of determining if something is loading, then it's probably the one that should determine
what should be rendered down here in the render method. So the way that I would actually probably
structure this in this specific case, when we're talking about having a loading thing
pop up on the page is right here, I would put my conditional this.state.is loading,
question mark, and if so, display our loading word. But otherwise, display our component.
Which means this conditional component wouldn't even need a prop called is loading.
In this
particular case, and over in conditional j s, I would just display the stuff that I wanted
it to display. And we see that it's still working this way. Obviously, the navbar and
the footer are gone. But the point is, this function should only really know what to do
when it's supposed to display. And our app component being the one that's maintaining
whether something is loading or not, can determine in its render method, which should display
here. In part two of conditional rendering, we're going to see some other ways that this
can work. But before doing that, I'd really encourage you especially since this is the
first time we're using component did mount in a real way to play with this code, spend
some time playing with the different ways we've already talked about here with conditional
rendering.
And once you're ready, let's move on to part two. There's actually only one extra little part
with conditional rendering that I'd like to cover right now. And that has to do with using
the logical AND operator, you may be used to using the logical AND operator to refer
to something on the left and something on the right as billions in determining whether
the entire condition should be considered true or false. So for example, true and false
would be false. Because with the AND operator, both sides need to evaluate to something truthy
in order for the whole thing to be true. Well, in reality, under the hood, what JavaScript
is doing is with the AND operator, it's determining the truthiness of the thing on the left. And
if the thing on the left is truthy, it just immediately returns the thing on the right,
which means when it's true and false, it returns false, because that's the thing on the right.
If the thing on the left is falsie, then it just returns false right from the beginning.
And so the AND operator can be a way to conditionally render something if a condition is true, or
just render nothing if it's false.
So with this little example that I've created, I've
added some unread messages in state as an array of strings. And you can see here it
says you have to unread messages because the length of the race too. But a lot of times,
you wouldn't necessarily want it to say you have zero unread messages, you may just want
it to instead not have any h2 there at all. Okay, using the ternary that we learned in
the last lesson, I could say something like wrap this whole thing in curly braces, and
then say, essentially, if this dot state unread messages that length greater than zero, then
render this array, but otherwise render nothing. So I could just say no, let me clean this
up a little bit. It's a little easier to read. But I can simplify this a little bit by getting
rid of my ternary. And my No, and just saying, check the truthiness of this dot State DOT
unread messages dot length is greater than zero. And so in other words, if that's true,
and render this part, however, if it's false, it will just render nothing.
And we can see
on our screen, there's nothing there. Once I add some unread messages back shows up. So the AND operator isn't strictly necessary,
because you could most of the time, just use the ternary where one of the results is no,
but this can really kind of simplify it just a little bit. And you may be seeing this every
now and then in the code that you look at with other people's react code. So that's
pretty much it with conditional rendering. Let's go ahead and move on.
Okay, let's practice some conditional rendering.
So here your challenge is given a stateless functional component, just this app component
down here, I want you to follow whatever steps it takes to add some state to it. I want you
to then have that state keep track of whether the user is logged in or logged out. Then
you should have a button that will change That state. In other words, a button that
logs them out if they're logged in or logged them in if they're logged out. And there should
be some text on the page that says whether they're logged in or whether they're logged
out. If you want an extra challenge, make it so that the button will actually display,
log in if they're not logged in and log out if they are logged in.
So as usual, give us
your very best shot. And we'll give you a few hints if you need them in just a few seconds.
But in the meantime, pause the video and try it out. Okay, really quick, some additional hints
that you might need, because this is actually putting together quite a few of the lessons
that we've talked about recently. So one thing is in order to add state, you'll need this
to be a class based component. And part of that is you'll need to add a constructor method
to that class based component for keeping track of whether the user is logged in or
not, you could use a Boolean is like in the Boolean either true or false. Adding a button
that logs the user out will require an event listener, which would be your unclick. Probably,
and then both the extra challenge and challenge part number four would require some conditional
rendering. So if you're feeling a little bit stuck, feel free to pause it again and try
it out.
Now that you have some hints as to how to complete each step. And we'll go through
this together in just a few seconds. Okay, let's try this out. So we need to make
our component into a class based component because well, actually, for a couple of reasons.
One is we want to keep track of state, which means we are required to have a class based
component. But we're also going to be writing an event listener. And technically, I could
just write another function that handles that. But personally, I prefer to have a class based
component and put my event handlers inside of the class itself. Okay, so to change this
to a class based component, we need to change function to class, it rid of our parentheses,
will extends react component return needs to be inside of a render method. We'll move
it there. And to add state to it, we know we need a constructor method.
Always call
super First, add a property called this dot state which is an object we'll initialize
it with is logged in of true or actually the start false. Okay, so that is steps number
one and two. Now we need to add a button that will change is logged in to true or false.
And so there's a couple things we can do. One is inside this div, let's get rid of that
and we'll add a button. And for now, I'll just say log in. And we'll play with this
a little bit later with the extra challenge. Now I need to add an event listener to this
so that the button being clicked actually does something. So add an unclick equals a
call this dot handle click. So anytime This button is clicked, it will call this classes
method called handle click well that doesn't exist yet.
So let's create it. Right here,
I'll add a handle click. And I'm probably going to run into a binding error here. So
I might as well bind this now. Let's say this dot handle click equals this I have a quick
dot bind this. Before I get too far, sometimes I'd like to have little sanity checks along
the way. I'm just going to put a console log here. Now we can check if I click the button
if it will console lock I'm working. Refresh the page and I get this login button. And
when I click it, okay, our console log is working just fine. And that's awesome. Now
the thing I want handle click to do is change false to true or true to false depending on
which one it currently is. And anytime I'm going to change state, I need to run this
dot set state. And remember, there's two different ways that I can set state two different things
I can provide to the set state method. Take a second to think of what those two things
are and which one is going to be most useful in this case.
So I can either provide set
state, just a brand new version of state, and it will smartly combine and replace the
current version of state. But since in this case, I actually need to know whether it currently
is logged in. Rather, if logged in is false or true, I need to instead provide a function
that has the previous state asked to it so that I can use that previous state to determine
what the new state should be. My function is going to return the object literal Where
is logged in, the value of is logged in is the opposite of whatever it used to be. This is a really concise way to change a Boolean
from false to true or true to false. Technically, you could also do an if else statement that
says if proof state.is logged in is true, then return an object Where is logged in as
false. Else return an object Where is logged in is true. But this way, I just say Just
give me the opposite of whatever it used to be. Now, we don't currently have a really
great way to see what the current version of state.is logged in is.
But I can do this
extra challenge right now and make the button say login or logged out depending upon what
the current version of status. So I might do that right here in the render. And the
first thing that comes to mind is just to have some button text saved in a variable.
So I can initialize this variable, and then I can say it equals, I'll use a ternary to
determine whether it says log in or log out. So if this.state.is logged in is true, I want
the button text to be logged out. If they're logged out already, I want it to say, login.
Man, instead of hard coding a login here, I will put button text.
Hopefully this will
actually show us whether they're logged in or out on the button, it says login, I click
it, and then it says log out. So I know under the hood, my state is actually changing. Awesome.
Okay, Part Four to display text that says log logged in or logged out, depending on
the current version of state is actually pretty straightforward. It's about the same as what
we already have. And so I might say, let display text equal essentially what we have here is
instead of log out and log in, it would be logged out. Or sorry, log in because if they're
logged in, then I want it to display a login logged in. Otherwise, no, no, but I have this display text. I could
put maybe an h1 here uses the display text. So the button says log in because it's a command
to log in, and it says I'm currently logged out. Then when I click it, it says click this
button to log out because you are currently logged in. And that's it for this practice,
then as much time as you need to really understand exactly what's going on.
And when you're ready,
let's move on. Alright, we've reached the final part of our
to do app and we're just going to hammer out this last little styling piece. And we'll
be done. So your challenge is notice we're here in the to do item component, what you're
going to do is make it so that the items that are completed look a little bit different
than the items that are incomplete. I'd recommend maybe graying the text out doing a line through
it, maybe turning it to italics or something like that, I'm probably going to do all three.
But whatever kind of styling you want to add, go for it and pause the lesson. Now give that
a try. Okay, so I'm thinking this will be pretty
straightforward. inside of my function here, I'm going to create a inline style to be called
completed style. And let's change the font style to be I like essentially, the styles
represent anytime that one of the items is completed, they will get this style. We'll
make it metallic and then we'll make it maybe a light gray color.
And we can put a line
through it with text decoration. And then the thing that I want to style is
the paragraph here that has the text of the to do. So I'm going to add a style property. And
I need to do some conditional rendering here that determines whether or not I should apply
these styles. So I'm going to say if props dot item dot completed is true. I'll just
do this inside of a ternary then I want you to apply the completed style. And if it's
false, then I'll just say no, which essentially means Forget it. I'm not actually going to
do any styling here. So if I Save and refresh this. There we go. My completed items are
grayed out, they're italicized, they have a line through them. If I make it incomplete,
it essentially takes those styles out. Awesome, great job on the to do app, hopefully, you
actually took the time to try and do a lot of this yourself. If you haven't, I really
highly recommend going back and actually doing these. Again, you might remember one of my
strong philosophies is that you'll never actually learn to create these applications unless
you actually do it by hand, just watching somebody else do, it isn't really going to
cut it.
Now coming up soon, you'll get a chance to build an entire app from the beginning.
And catching up on things like this to do app and actually trying it yourself is going
to really make that task a lot easier. Once you're ready, let's go to the next lesson. In our past lesson about lifecycle methods,
we talked about a lifecycle method called component did mount, I want you to take a
second and see if you can remember what component did mount does. component did mount is like
a hook in our react component that allows us to run some kind of code immediately after
the component first mounts to the DOM. I mentioned when we were talking about lifecycle methods
that one of the most common uses for component did mount is to get data from somewhere so
that your component can do what it's supposed to do.
As a quick refresher, I can add a lifecycle
method right here as a class method has to be spelled correctly though it has to be component did mount and let's just take a look, if I do a quick
console log, see that it ran our console log and it ran the console log immediately after
the component finished mounting to the DOM. Well, like I said, right here is where we
would get any kind of data that's required for this component to display what it needs
to display or do what it needs to do. And so for this lesson, we're going to be using
a couple tools that are really helpful for doing that. The first one is a built in JavaScript
tool that's more or less new, called fetch. and fetch is a nice, easy promise based way
to perform HTTP requests, so that we can get any kind of data that we need.
I'll put up
near the top here, a link to the MDN docs on the global fetch function. Another tool
we're going to use is an API called the Star Wars API. Heavy school, we really like the
Star Wars API, because it is cores enabled, which means that there are no issues with
our front end application getting data from their database, you can find the homepage
for the Star Wars API right here. Pretty easy to use. And the data that comes back is pretty
fun to play with. So feel free to take a look at that website, too. And another resource
that I figured out, add here is a medium article that talks about promises just in case you
aren't feeling as familiar with promises as maybe you should. But the truth is, there's
a million articles out there about promises. So you may have to read through a few of them
and just practice them yourself until you feel comfortable with them.
Okay, so let's
get started with this inside of my component did mount I'm going to use fetch, which I
use by just typing fetch. And this is a global function. So this should just work. And here,
I'm going to put in the URL where I'm going to be getting the data from. So I'm going
to put in the Star Wars API endpoint here. And we're going to search for slash people.
And we'll just get the person with the ID of one, which happens to be Luke Skywalker.
And that's all we need to do to use fetch to get some data for us. And I'm going to
resolve the promise by using a dot then, which will receive a response that is not quite
yet in the format that we need it to be in. So I'm going to use a method called dot JSON,
which will turn this into a JavaScript object for us.
And next in my promise chain, I can
chain on another dot then which will actually receive the data that we want. At this point,
I'd like to do something just like console log the data. So you can see if that worked,
we'll refresh this. And it looks like we got some data down there. It's an object with
some properties, like a name property, which we see is Luke Skywalker and some other properties
that describe Luke Skywalker.
Now that I have some data and need to get this to display
on the screen Somehow, I want you to pause the video and just try thinking through what
that would entail. How are we going to get this data that we just received from our fetch
call to actually show up inside of our browser? Well, now that my component has received the
data, if I don't save it somewhere, it's going to disappear. And if you remember the way
that we save data, Within a component is by state.
So right here in state, I'm going to
add something like character, maybe, instead of equal to an empty object, I chose an object
because I know the data that's going to come in is going to be an object. And then right
here where I'm receiving my data, I want to make sure that I save it in my state. So I'm
going to set state what's the video again, and see if you can write the set state that
we're going to need to do in order to save this data to our component state. Anytime
we want to change the state, we're going to call this that set state. This case, I really
don't care what the previous state was, because I just want to change this state character
to be the data that I just received. So I'm going to provide an object here, say character is the data that I got.
Now, unless I'm inspecting
this with my dev tools, I don't currently have a way to show that this is actually working.
So down here, in our render, I'm just going to choose one of the properties probably name
and see if that will show up on the screen. inside of my curly braces, I'll say this dot
State DOT character, dot name, refresh the page and see what happens. Hey, now this API
call is fairly quick. It made the call, waited for a response, got the response, set the
state and then displayed Luke Skywalker on the screen all pretty quickly.
But if the
person using this app has a really slow internet connection, or the API is really bogged down,
or for whatever reason, it's taking a long time for this request to complete, there's
actually going to be nothing that shows up on the page until that request is done, which
is a little bit off putting for a user. So although this doesn't directly relate to this
lesson, fetching data from an API, this is a great place to talk about having some kind
of loading message that lets the user know that the data is on its way.
Now usually,
I like to use some kind of fancy loading spinner or something like that. But for now, let's
just make it display the word loading until that data comes back. This will illustrate
a little bit of the power of saving state in your component and updating state as you
go through a really simple way to do this is to add to my state, a Boolean as to whether
or not we're loading, I'll start by saying it's false. And then right before we perform
our fetch, I'm going to change it to true. Pause the video and see if you can figure
out how to change loading to true. Okay, remember, anytime we want to change state, we're going
to use set state.
And I don't care again, what the old state was, I'm just going to
provide an object and say, loading is true. Now what we need to do is figure out how to
display the word loading. If state says that the data is loading. Pause the video again,
and see if you can write something down inside a div that shows the word loading if this
dot State DOT loading is true. Right now I have this dot State DOT character dot name.
Here, you can see really quickly when I load this, that there's a moment where it's blank.
So what I could do is right before my return, I could say something like text equal to and
then provide an if else statement. Or I could shorten that by putting a ternary statement
here.
So I'm going to say simply, is this dot State DOT loading true? If so I want the
text to say, loading. Otherwise, I want the text to say this dot State DOT character dot
name. And instead of having this done here, I can put in my paragraph or whatever element
of text I want. And I'll say it before I refresh this, I want you to try and think like the
computer and see if you can figure out what's going to happen. Let me refresh this. And
what's going on here. It says that it's loading constantly. To thank for saying it, why would
it be doing that? Why is it consistently saying loading rather than changing it to the character's
name? Well appear we set loading to true, but we never again set loading to false.
And
so this is always evaluating to the string loading. So now pause again and see if you
can figure out how to fix this bug. This one's pretty easy here. When we're setting state
of the character. We're also going to set the state of loading back to false. Let's
refresh. You'll see it said loading for just a short
amount of time and And then it resolved to Luke Skywalker. Awesome. Okay, so we have
successfully used component did mount as a place to fetch our data from an external API,
so that our component can do what it's supposed to do. In theory, this components job is to
display one of the characters from the Star Wars API. And it needed the data from the
Star Wars API. To do that. We've also implemented a loading feature that lets the user know
whether it's currently loading or not, so that they don't just give up on our site and
leave.
I also think this is a good time to take a step back and remember how awesome
it is that react is so declarative, if you were doing this with vanilla JavaScript, or
jQuery or something more imperative, rather than simply having a ternary, that checks
the current state of your loading variable and deciding whether it should display loading
or not. And then just say whatever that is display the text. Instead, you would have
to manually get an element by its ID, change it to loading, start the API request, and
the data came in, you would have to get the element by its ID, again, you'd have to change
some other kind of style, you'd have to change the word to display the data that just came
in.
Whereas here, we simply get to be more declarative and deal with state and say, whether
we're loading or not tell it when to say that it is loading, tell it when to say that it
is no longer loading, and react will handle the rest. So this is pretty cool. But it does
require a completely different way to think about web development. A few minutes to play
with this code, feel free to go check out the Star Wars API and try getting some other
resources, see if you can get different things to show up on the screen. And when you're
ready, let's go to the next lesson. Let's talk a little bit about forms in react forms
tend to be actually a really important part of having a web application. And I found from
teaching students at vi school that it's actually a rather tricky part of react, because we
do things a little bit differently than we're used to when it comes to forms.
So I'm going
to do something a little bit different in that I want you to do a couple things before
continuing on with this lesson. The first thing is I want to make sure that you understand
state as well as you can, you don't have to be an expert with it. But as long as you have
been able to follow along with everything we've talked about so far in state, and been
able to complete the challenges, you should be good. If not, please go back and spend
some extra time with state. The next thing is I want you to actually pause this video
and go to the React documentation on forms, I put the link right here.
And this does a
pretty thorough job talking about the concept of forms in react. Once you've done that you
can move on. So with forms in react, we actually do things a little bit different than we're
used to with vanilla JavaScript. In the vanilla JavaScript Dom API, you create your form in
the HTML. And once the user decides to submit the form, you go through all of your form
inputs, and gather all the data together pretty much at the last second. And that's when you
would do any kind of form validation that you need, and so forth. Well, with react,
we're going to do it a little bit differently. Instead of waiting until the very end, right
before submitting the form together all of the information, we're actually going to constantly
keep track of all the information in state, which means on every keystroke, we're actually
going to update state so that we can always have the most updated version of what the
user is typing into the form.
To really illustrate this, let's just start with a single text
input. Down here, instead of a div, I'm going to render a form. And we'll put a
single input inside of there. Give it a type of text. Let's give it a placeholder for now, just
to keep things simple. Let's see we're gathering the first and last name of person. We'll start
with first name. Okay, so like I said, normally, our form might have a button that says submit
the form. And at that point in the vanilla JavaScript Dom way of doing things, we would
gather all of the information typed into all the inputs. But in react, we want to watch
for every single change to this input box. So think for a second how we might do something
like that. Well, input boxes have an event that can get fired called on change. So what
we might do is every single time the input changes in the input box, we will run a function.
Let's call it this dot handle change.
This function obviously doesn't exist yet. So let's
create it. Now my goal is to make it so that every single time somebody types in here,
I actually update state and I want to do a couple things. I want to Grab the current
value of this input box every single time it changes. And I want to then update state
to reflect what the current value of that input boxes. Well, first of all, my state
currently doesn't have anything saving anything right now, right? So I'm going to add a property
called first name will just started as an empty string.
Now I have something that I
can update every time the handle change function runs. Okay, well, to update, I use this dot
set state, anytime I want to change the state. Truthfully, I don't care what the previous
state was, I'm just going to provide an object here that says the first name property should
become something. Well, what am I going to put here? Well, I need this to be the current
value of my input box.
If you're familiar at all with vanilla JavaScript Dom API, then
you know that when events fire, they pass a pre determined parameter into our function.
We don't get to choose in this instance, what's actually going to be here, it's always going
to pass to us information about the event that fired. And this event has some really
important information. For example, I can get access to the value of the input box by
saying event got target. Target represents the element in which the event was fired dot
value. And that's the value of the input box. So what I've done here is I've said every
single time a character is typed into this input box, run the handle change function.
And the handle change function changes the state, so that the first name property of
state is updated to reflect whatever the current value of this input box is. I can't open the
dev tools and inspect state inside of scrambler.
And so I'm just going to create a little h1
that will display whatever the state is. So we can see it. And now I'm actually going
to run into a little error. You'll see that it says I can't read the property set state
of undefined, see if you can figure out what I'm missing. Anytime we have a class method
that's calling set state, we need to make sure we bind it inside the constructor. And
so inside the constructor, I'll put this dot handle change equals this dot handle change
that by end of this.
Okay, so let me refresh this again. And I will start typing and you'll
see every single character is upgrading state. Okay, well, I have something that's going
to violate the DRI principle, don't repeat yourself principle. Now what's going to happen
if I want to create another input for my last name. So I've made another input, that is also running
my handle change function. Let me initialize a last name property in my state. And I added
my h1 to show what the last name property of state is. Okay, so I have a first name,
last name, first name works great. But what happens when I type in the last name? Notice
it just gets rid of everything from the first name. That's because I've hard coded into
my handle change that it's updating the first name property of state. Obviously, one way
around, this would be to make a whole extra function called handle last name change or
something like that. And make this on change be a different function altogether. But that's
not going to work in a larger form that may have like 50 inputs or something crazy like
that.
Now instead, what we're going to do is we are not going to hard code first name
here. And we're going to give a name property to our inputs. That perfectly matches what
our state is. First Name, capital N, and last name, capital N. And remember, up in our handle
change, we have this event that we're receiving, well, this event has a bunch of information
about the input that is firing this event. For example, we grabbed the value of the input
box. But I can grab any part of the input object that I want, not only the value, but
I can also grab the name property. And so to the left of my object here in the property
name here. I can say event dot target, which is my input box.
Got name, which is the name
property. This isn't quite right, right, because this is a syntax error. If I want this to
actually represent the first name, property or the last name property, I need Make sure
to wrap this in square brackets. And this works because the name property is a string.
And if I'm describing a string property name inside of an object, I can wrap it in square
brackets. This is just a principle of JavaScript that you may or may not be familiar with.
And so now when I refresh this, anytime I type into the first name box, I get a change
to my state in first name. And anytime I type into my last name box, I get a change to the
last name. Okay, as a quick aside, this same principle here is going to work whether I
am using a type of text, or anything else that's text based like an email, or phone
or number, all of those are essentially going to use this exact same handle change function.
And you need to make sure that you give it a name property that perfectly matches the
property and state and that you pass your on change function to it.
Now I'm actually
splitting forms into a two part lesson. And in the next one, we're going to talk about
some of the other types like checkboxes, radio buttons, text areas, and select boxes. But
before we get there, there's one more thing I want to touch on. And that's the concept
of a controlled form. If you did what you're supposed to do, and went over and read the
React documentation on forms, you read about controlled forms. The idea is that we actually
want what's displayed inside of our form to perfectly match up with what is in our state.
Right now, state is being reactive, as in every time the input in the box changes state
updates, according to what's in the input box.
Well, with a controlled form, state actually
directs what is inside and showing up inside of the input box. This is kind of a splitting
hairs distinction. But it really jives well with the idea that state should be the single
source of truth, it doesn't have to be that complicated, the only thing we really need
to do, especially with these text inputs, is add a value property. and the value should
always be this dot state, dot, and then whatever property that box is holding, first name, last name. And when single elements start to get too
long like this, I like to put each of these attributes into their own lines. Okay, that's
a lot better.
Okay, now we can see that everything, I'm going to refresh this, everything is still
working essentially the same as it was before. But now what is showing up in this input box
is because of what the current version of state is, in other words, I'm forcing the
value or what shows up inside of the input box to exactly match what state is also going
to give you one quick best practice that will help you avoid a really difficult to debug
bug that could come up in the future. In this case, we're not seeing it. And I'm not going
to worry too much about explaining what that bug is exactly. But a really good idea is
instead of directly accessing the name and value properties, by drilling into the event,
that target object here, you can save yourself a lot of grief by simply pulling those values
out of the target before you set any state. Using some basic object D structuring, I can
say name, value equals event dot target. Then down here, I can just say name, value. If
this is something that you're actually super interested in understanding, you can look
into reacts synthetic event.
And you may get a better understanding of why this is important.
But it can be really helpful to make a copy of the name and value before you run setstate.
Okay, that's enough for this part of the lesson. Take some time to go over this again and digest
it, feel free to practice with it. We're going to talk about forms part two next, and then
we'll have a practice that goes over both of these parts together. So far, we've talked about some of the most
basic input types when it comes to forms, anything text based is essentially going to
act the same way that we've talked about in the previous lesson.
But unfortunately, forms
are a little bit more complex than that. And with some of the other elements that you can
use, things start to get a little bit more complicated with react, but it's not too bad.
So let's walk through it. Down here, I've made some notes about some of the elements
that I'd like to talk about the first one and probably the easiest to understand is
the text area element. If you've used the text area element in regular HTML before,
you know that it is not a self closing tag, like the input element, but instead has a
closing tag. If I refresh this page, you can see that it's essentially like an input box,
but it's a little bit taller and the user has the ability to make it bigger or smaller.
We also have the ability to change the default height and width with properties called rows
and columns and in regular HD Well, if you wanted to pre populate some text in here,
you would do so by typing it in between the opening and closing tags, or rather the inner
HTML.
Well, what react has done is they wanted to make text area much more similar to the
input element. So in react, there's a major difference in the text area element in that
it is a self closing element. This is actually really nice, because we are able to use the
value property now. And we can use it exactly the same way as we were with an input. This
is nice for consistency. And it also makes it really easy to update the value of the
thing inside the text area by updating state. So you can see if I were to add some default
value in here. That's what shows up in my text area element. And that's it with text
area. Let's move on to checkboxes. checkbox is just a type from input. So input type equals checkbox. But one of the major differences is that you
are not going to use a value property like we did with text area or input.
Instead, the
idea of a checkbox is that it's either checked or it's not checked. This means that we are
going to add a checked property here and I'm going to start putting things on their own
lines will have a checked property. And this is going to be determined by some kind of
Boolean because a checkbox is either checked or it's not checked. And so checkboxes typically
maintain Booleans in state. For this example, maybe we are checking if the person that we're
referring to is friendly. Now in state, I haven't yet defined this.
So I would come right up here to state. Ad n is friendly, and maybe we'll initialize
it with true for refresh this, you'll see that I now have a checkbox and it starts out
by being checked. We'll notice that if I click it, it's not letting me uncheck it. Think
for a second why that might be? Well, down in my check box, I've told it that it is checked
if this.state.is friendly is true. And essentially this true value is being forced upon this
input.
And so even if the user tries to uncheck it, React will say, Nope, it is actually checked
because this value is true. So you might have noticed something popping up in the console
that says that I've provided a value prop without an unchanged handler, essentially
rendering a read only field. And that's what we're seeing here. It's Read Only I can't
make changes to this because I haven't taught it how to make changes and how to change state.
Well, this is where things get tricky, because what I don't want to do is add an unchanged,
that is looking to something like handle checkbox method. Right? It would be nice if I could
just use my existing handle change method to handle changes on a checkbox. And so we're
gonna see how you can do that. First, I'm going to put this to handle change.
And just
like our other inputs, I'm going to give this a name property that is the same as the thing
in state is friendly. And now Give me a second to make this look a little better in our form
over there. Okay, that looks better. And now the tricky
part comes in. Because in an input box, we're keeping track of what's being typed into the
input box.
You might remember from our handle change, we are grabbing the value event dot
target dot value, an updating state with the new value. Well, our checkbox doesn't have
a value, it has a checked property. And the checked property is actually going to return
either true or false. So what we're going to need to do in order to use our same handle
change function for our checkbox, is we need to check if the element that is being interacted
with in the form is a checkbox or not. And so there's a couple things that we need to
pull out. First of all, notice how we have type equals checkbox. Type is a property that
we can pull from event target. So besides just the name and the value, if it's an input
or a text area, you can also grab the type. And then just like we discussed how checkboxes
don't have a value, but instead have a checked property, we can pull that from event target
as well.
And so now we know that I can check if the type is a checkbox, I won't be able
to do this, this dot set state because I won't have a value property. But instead we'll need
to change the name which is is friendly to whatever the current value of checked is.
You could do an if else statement, or I could just do a ternary here. So I can say is the
type equal to checkbox? If so, we're going to update state in a certain
way. But if it's anything other than a checkbox, we'll use our existing This dot set state. Now here, we will also
run a set state. And we are going to access the name property. But instead of using value,
we're going to set it to whatever the value of checked is.
Let me open this up a little
bit so that it's a little bit easier to read. And now when I refresh, let's see if I'm able
to update my checkbox. Now when I click the check box, it's going through my handle change,
it's seeing that the type is a checkbox. And so it's running this, this that set state.
And when I go over to my other input boxes, I can still say, name, and it's updating state in a different way.
And while we're at it, to get rid of the warning that we have in our console, let's add an
on change to our text area, so that it stops yelling at us.
Excellent. Well, now let's
talk about radio buttons. Because radio buttons are kind of a combination of the input type
text, and the checkbox. What I mean by that is that they are going to use both a value
property and a checked property. So I'm going to make a copy of my checkbox, so that I can
quickly get something prototyped up, I'm going to change the types here to radio, let's give
the name of maybe its gender. And now notice that I'm giving the same name to both of my
radio buttons.
What this tells the DOM to do is to make sure that I can only choose
one of these two radio buttons, wherever they're also going to have value, the value will be
slightly different. So maybe first one is male, and the second one is female. And I'll
update my label here. And let's put some breaks in there. Now notice
what happens when I go over here. Again, I can't change them. But if I click on his friendly,
notice that it chooses one of these two to be checked. This is kind of quirky. And the
reason is, first of all, because I copied and pasted, which sometimes leads to funny
bugs, it's still saying that it's checked if his friendly is true.
But this is where
radio buttons are a little bit different, because I can't just say it's checked if some
value in state is true, because radio buttons jobs aren't to maintain true or false values,
right? That's what the checkbox is for. Instead, I want this to be checked if the value of
this dot State DOT gender is equal to male. And similarly, if this one is equal to female,
I don't have gender maintained anywhere in state, so I'll need to go update my state
up here.
Maybe we'll just start gender as an empty string. Now, when I choose this,
it will let me choose one or the other. And under the hood, it's maintaining a gender
of either male or female. Again, since I can't pull up the dev tools in scrambled, let's
go down here and just display something here. Okay, and we should probably use some kind
of conditional rendering. So this doesn't show up until one of these is chosen, but
that choose male and female, it's updating state, and therefore updating the text that
we're seeing down here.
I think this is probably a good point to mention that a lot of this
stuff may seem really complicated and different from each other. And it's just important to
know that you're not necessarily expected to have all of this memorized. Honestly, I
end up coming back to some previous examples that I've written just so I can remember this
syntax. This is probably also a great time to mention that there's a really excellent
library out there called Formic.
There's a few of them, but I'm just gonna put the name
right here. So you can take a look. Formic basically takes all of the pain out of writing
react forms, it's a library that you can install and just use their API to make your life dealing
with forms much nicer. Okay, the last form element that we're going to talk about is
the select box. And in regular HTML, you're probably used to having a select with options.
And fortunately, React has chosen to use the value property again, so that we can easily
determine which of the select elements is chosen. And also to very easily be able to
update state, though for example, maybe we are deciding what our favorite color is. We'll
have a state property called favorite color, and the value of this whole element is going
to be whichever of these options we choose. First thing, let me put favorite color up
in my state. And we'll just start it off as blue. Okay, and then down here, I'm going
to make sure that I'm watching for a change on my select box.
So unchanged, I'm still
going to run my handle change, I also need to give it a name, just like I did with my
input boxes will make sure that this matches the name and state. And then the only other
change I need to make is make sure that my options also have value. And the value here
is going to be whatever I want the different options to be. So this will be the value under
the hood.
And then the text here in the inner HTML is what will be displayed in the select
box. And that's probably good enough. Oh, and it looks like I put my slash in the wrong
place here. Okay, let's give this a break. So it's on its own line. And maybe put another
label here. And yes, I understand this form is very ugly
right now. But my click my drop down box, you'll see I have my options.
And before I
select something, let's just put another thing down here. So I can see that state is updating. Okay, notice that my state initialized correctly.
And when I change this, it's changing the value of state. what's so cool about the way
that react has chosen to implement the API regarding elements and forms is that it makes
it so that we can write a single on change, rather handle change. It had to do one workaround
with the checkboxes simply because the philosophy behind checkboxes is so different than all
the other elements. But essentially, we're reusing this one handle change, and it's working
for all the elements in our form. Yeah, I totally get that this is a lot to digest,
we're gonna do a practice right after this, that should help cement this information a
little bit.
Don't feel overwhelmed so much with understanding or rather learning all
of the syntax of every one of these elements, that may distract you from all of the other
coolness that react has to offer. Instead, don't be afraid to just practice this a couple
times, and then come back to it whenever you need to, eventually, you'll gain a muscle
memory that will help you remember all of this. One last thing that I failed to mention
in the previous lesson was how to actually submit this form or do something at the end
of filling out this form. Kind of two general ways that you could do this in either way,
it's going to be a good idea to put a button in your form of some type.
Now in html5, the
button element if it's found within a form, acts like the old input type submit, if you're
familiar with using that, where you would give it a value that displayed the text on
the button, and so forth. I personally really dislike the way that input is used in so many
different ways. And so I never use the input type submit myself. Instead, buttons in html5,
if they're found within a form. When they're clicked, they are a submit button. And they
will fire the on submit of the form itself. So when you want to do something, when you're
finished with the form, one thing you could do is to just add an on click on your button.
Personally, I like to handle that action on the form itself. And so I will have an on
submit handler. And we didn't write this but it would be just as easy as creating another
method that's called handle submit and doing something like submitting the form to an API
or something like that. Okay, take a deep breath, you've basically finished all of the
most important parts of forms.
We've talked about input type, text, and other text based
inputs like numbers and passwords and so forth. But we've also learned how to handle checkboxes,
radio buttons, and select boxes and text areas. Okay, let's move on to the next lesson, which
will be a practice of forms. So let's practice building forms. Your challenge
is to wire up the partially finished travel form below so that essentially it works in
react.
This challenge is actually one that we use at vi school and the URL for the original
challenge is right here, you'll probably want to go there so that you can see exactly what's
supposed to be done. Now in this goal will use this as in plain HTML forms challenge
so it doesn't really have anything to do with react, but I'm just adapting it for react
for this lesson.
So pause this lesson, go take a look at this website. Learn some more
about what you're trying to accomplish in this form, and give this a go. Alright, so there's a lot of different ways
that we could approach this, I think what I might do is initialize everything with state
first, and then start wiring things up one at a time. Okay, so I know that my state is
going to have a first name. Last name.
We'll also do age, which actually have a little
bit of a question myself on, but I'm just going to initialize it at zero for now, and
then try something a little bit later. Let me scroll down here, I know I'm supposed to
have under and I have a select block for location, I'm pretty sure this is supposed to be destination.
So I'll say destination, then a checkbox for dietary restrictions.
Now, what's actually
going to be there for dietary restrictions is a number of checkboxes. And because they're
checkboxes, it's possible that they will check multiple boxes. And so if I'm going to have
multiple dietary restrictions, what I might do is choose to take this as an array. And
okay, that seems to be the last thing because here's my Submit button. Now that I have my
state initialized, I'm just going to start putting some of the things that I know will
need to exist in my existing elements here.
So we'll start with my inputs, I know that
I'm going to need a name property for each one. Now I'm going to need a value for each
one. Actually, this is going to be determined by state. So this will be this dot State DOT
something I know each one is going to want to be able to change. So I will have an on
change will probably call it handle change. While I'm added I'm going to put everything
on its own line. Okay, so the names will need to match the parts of state that they're representing.
So this will be first name, last name, and age. And I'll actually have the same thing
for state. So this will be first name, last name and age. So that looks like I lost my
curly braces there.
Now maybe before I go creating a bunch of extra elements, I may
finish this part off and make my handle change method. Right here, I will need a handle change.
I'm going to take an event. And before I forget, I should probably find this I know that I
like to pull some of the elements from the event that target.
So for this right now,
I just need name and value will add to this later when we get to the checkbox. And I'm
going to set state here whatever name I'm concerned with changes
to the new value. Okay, so the buggy thing here is that this starts with a zero. Let's
go down and see if these three inputs are working correctly. So with your name, going
to put this dot State DOT first name, base, and this dot State DOT last name.
If I type in these boxes and see if it's working
great. The same for age. And it already says zero. But if I change this to something different.
Okay, that works. And now the thing I actually wanted to test was to see if react complained
when I started this as No. And it does. Okay, and it looks like it just doesn't like that
the value on the input is no. So it recommends using an empty string. But part of me going
out and doing a bunch of research this will just have to do for now. Okay, so after a
refresh, you can see I don't get my zero age anymore, which is smart, we wouldn't want
that showing up as a default of our form. And it looks like so far, so good. Let's go
down and fill in some of these new elements here. Let's start with the radio buttons for
gender. I like to wrap my radio buttons in a label that said that the person could also click
on the text of male or the text of female and select the associated radio button because
the text is a parent of the radio button.
So I'll just put the label as a parent of
my radio button which is an input Type radio. And I like the text to be on the right side
of the radio button myself so that the radio buttons are nice and lined up on the left
side. And remember the radio buttons were kind of a combination of checkboxes where
they have a checked property and also the text inputs where they have a value property.
So I'm going to be adding a lot of stuff to this radio button, I'm gonna go ahead and
start putting things on their own lines already.
And then we'll say response has a name, which
will be a gender value, in this case, it will be male. And we're also going to have the
checked property. This one is a little bit trickier because it's going to say this radio
button is the selected one. If this that state that gender is male, then we'll have our on
change to be our this dot handle change. And let me go ahead and just copy this and change
it to work for female as well. Another great here. Hey, let's refresh the page and see
what we got male and female, and it looks like I can check those. Let me see down here,
if that's working. So under your gender, we'll put a start state that gender doesn't start
as anything and choose male. And there we go. Change it to female. Perfect. All right,
we're cruising.
So let's do our select box now says the select box for our locations or destinations.
And this is going to be a select box. And we know we're going to have some options in
here. And let's put before options. Obviously, this
is not a great airline that's flying to only three or four locations, but whatever. Now
I remember that our select and our options all take a value property. They're a little
bit different from each other, but I'm going to go ahead and just add a value. Okay, the
value on my options is simply what state should be if this option is the one that's chosen.
So this is where I'm going to put my actual locations. So I might say something like Germany. And I'm going to keep this lowercase for the
extra value just to stay consistent with how I have things elsewhere. Let's do Norway, the North Pole. And why not, say the South Pole. The value
of the select box is not the options that we have, but rather the chosen option.
So
this will be determined by state as part of a control perform. We are calling this destination.
Then just like our other ones, we need to make sure that this has a name, say his destination
again, it needs to match the property and state. And we'll have our same on change,
which is the standard change is getting long. So let's put it on its own lines. And down
in the Display area, we will put destination from state. Now you'll notice here that it
has automatically selected the first one, but doing so has not actually updated state.
So my destination is still empty.
If I want to Germany, I would actually need to switch
to Norway, and then back to Germany to actively choose this as my option. And so what a lot
of people will do is they'll just put an option at the top that maybe we'll leave empty and
put something like something like that. Okay, Germany gives me Germany and I can actually
actively switch to any one of these that I want. Okay, well, we've saved probably the
more difficult one for last. And that's our checkbox. I feel like I've had some clarity
since I first started state. At the beginning of this lesson, I created an empty array for
my dietary restrictions. And I'm thinking it's actually going to be easier if I save
this as a sub object where I have an option for each one of my dietary restrictions and
the value is going to be a Boolean. So instead of trying to manipulate my bullions into some
kind of text value. Instead, I'm just going to create an object.
And each one of these
will represent a Boolean of some kind, I will probably want each of these to be unchecked
as a default. So I'll just say each one is false. The is kosher. Free. That should be
good enough. So now I'll need three checkboxes, each one representing one of these three properties
down here in my form. Again, I will wrap everything in a label type of checkbox. Name, the vegan unchanged will continue to be this handle
change, which if you remember, we're going to need to update in order to correctly handle
the checkbox. And then I need something to direct whether or not this is checked. And
this is going to be a little extra nested level here.
So it's going to be dietary restrictions.is
vegan. And as part of my label, I'll just put a label that says vegan. Okay, so I'm
actually just going to create a few of these and update them. So I have is vegan is kosher. And this one was lactose free.
Okay, let's take a look and see what that looks like. Okay, awesome. Now notice that once again,
I'm not able to change any of these checkboxes. If you didn't get this far, when you did this
yourself before we started doing this together, pick the time now to see if you can update
our handle change so that it can handle the changes in a checkbox.
Okay, so once again, the checkboxes don't
have a value property. And currently, our handle change only is able to update things
with the value. But we know that we're going to have to check if the type is checkbox.
So I'll need to pull the type from my element. And I'm also going to want to see if property
is true or false. Or rather just see what the check property is, then what I need to
check is if the type is a checkbox, I'm actually going to do my
set state on its own line, it's gonna get a little more complicated.
Remember that in this case, I can't just say to set the state of name checked.
That's because I've chosen to have a nested object here.
Apparently state does not have a property called is vegan or is kosher. Instead, it
has a property called dietary restrictions, which has a property called is vegan, or is
kosher. Now normally, React is smart enough to know that if I'm updating just one part
of state like the destination, it will combine that with the rest of state.
However, I'm
not 100% sure offhand, if I update just one part of a nested object, if it will also update
the rest of state. So I'm going to be live testing this here with you. Let's give it
a try. First thing is this won't work either way. So this will have to be dietary restrictions.
Be an object, and we will update the name. Before I can test this, I need to finish my
ternary because this is broken Currently, there will say otherwise. This dot set state
name value just like we had before ever feeling this isn't going to work, but let's give it
a shot. So no errors so far. That's good. You know, just put something in here, we'll
see that my name is working.
Now if I check vegan, it doesn't seem to like it, it thinks
that I'm changing something from a controlled form to an uncontrolled form. And that has
to do with the way that date is updating out Fortunately, I think I should be able to use
the object spread notation, which means what I can do is pass in the previous state. If
you remember when we talked about that state how I can either provide a brand new version
of state or I can provide a function that receives the previous state as a parameter
and uses that to update state. I'm going to change this to the second way and I return
a new object and inside of dietary restrictions, going
to take all of the property These from proof State DOT dietary restrictions, and then update
the rest. And it actually looks like maybe scripted does not have the ability to do object
spread notation.
It really depends on what version of ECMO script you are transpiling
using Babel. In this case, it seems like the object spread notation doesn't work in scrubba.
But at this point, I think it kind of worked myself into a corner. One workaround that
I can do and probably will do for now is to just get rid of my sub object, dietary restrictions.
And make each one of these their own property on state, we just got promoted. which case, I can probably simplify this quite
a bit and go back to the way it was. So we'll get rid of dietary restrictions, we'll get
rid of this name checked. And now that is vegan is kosher, and is lactose free are kind
of first class citizens here in state, I can simply update by its name and determine whether
it's true or false.
Let's try this. Okay, we're doing some live debugging here, it says
that it cannot read property is vegan, of undefined. And notice that I still have my
checked saying this dot State DOT dietary restrictions. We don't need that anymore.
Or handle change and try again. Okay, so now I should be able to enter something as a first
name, which shows up in my name, and then choose some of these. And oh, we haven't updated
our dietary restrictions display yet. Down at the bottom, let's just see if we can get
this to work your dietary restrictions, say, vegan.
State that is vegan. And we'll just
do the same with kosher and lactose free. You'll notice that it looks
like they're starting out empty. If I had checked them, it's not actually displaying
any text here. Isn't is react does not display Boolean true or false as text on the screen
unless you go out of your way to make it text. But one quick workaround that I could do is
I could put another ternary here that says you should display Yes, if it's true.
No,
if it's false, then here, I actually get the nose showing up. Let me put these each in
their own paragraphs, so that they don't mash together this way. And you'll see vegan, no
kosher, no lactose free No. When I select some of these, those have changed. Yes. Or
another fun practice that would just be a regular JavaScript challenge is to try to
get it to display the words vegan, kosher and lactose free is a comma separated list.
I won't do that here. Because I've already taken up time just trying to debug this with
you. If you want, you can pause the lesson and give that a shot might be kind of a fun
challenge. And with a little bit of workaround, and having to change a little bit of our state,
we have been able to successfully build our form. It's obviously not very pretty, but
it seems to be working. So if I fill everything out, not 9999, as it turns out, looks like
oh, I have to select the destination.
Let's go to Norway. It looks like everything has
filled that correctly. I mentioned at the beginning of learning forms, it's a kind of
complicated process. And forms in general are very important when it comes to web applications.
Obviously, they're not always going to be filling out lengthy or forms like this. But
if you think about it, anytime you click a checkbox, or anytime you have a radio button,
or a signup form, or a login form, or anything like that, a lot of that is using forms. So
really understanding this is going to help you be a better developer for web applications
that users can interact with. So although I said it's not necessarily important to have
each input type syntax memorized, it's still a really good idea to practice this, play
with it, see if you can really understand it so that when the time comes to build the
form in your react app, you can do so relative ease.
Thanks for your patience while we went
through and debug some of this stuff. Hopefully, that was a good exercise in general. When
you're ready, let's move on. So when we built the travel form in react,
you may have noticed that a lot of the time we were scrolling up and down and we have
an component here that's 146 lines long. Now you'll notice that A lot of this space is
being used as display logic, right? It's showing the form, it's displaying UI, it's creating
elements, all of this happening inside of the render. But then we also have a place
where we're maintaining state. And we have our handle change function, which is doing
some business logic.
You know, there's been a study done that shows that a programmers
ability to understand the code that they're looking at diminishes dramatically, when the
file that they're looking at is one in which they have to scroll to see everything. And
I've noticed that with my students as well, if I have code that's too long, and I'm scrolling
around the screen all the time, it's very easy to become disoriented and lose your place,
and makes it much more difficult to actually understand what you're looking at.
It would
be nice if we separated our concerns between the UI logic or the rendering logic, and the
business logic that actually mandates how the rendered logic changes. And so this idea
emerged a few years ago of having a presentational component and a smart component or component
that's in charge of the business logic. There's a lot of different names that you'll hear
presentational and container components, smart components and dumb components, containers
and components. But they all refer to essentially the same thing. The idea is that you have
one component whose job it is to maintain state, and to have the methods that update
state. And then for that component to essentially delegate all of the UI logic or presentational
logic to another component. That's called the presentational component. That presentational
component will only be in charge of receiving props and displaying things correctly. If
you'd like you could read den epor mobs, medium blog post where he talked about presentational
and inner components at this URL.
And if you're unfamiliar with Dan Abramov, he's one of the
primary developers of the React framework. So let's take a minute to organize some of
the code that we've written here. First of all, I currently have everything happening
inside of my app component. And I just did that for simplicity. But in reality, I want
my app to render my form, and let my form do all of the for me things. So I'm going
to create a new component called, let's just say form dot j, s. And I'm essentially
going to take everything here, put it over and farm, clean up a few things. palette form, and export form. And then over
in app, we will make sure to import the form. And since our form is handling all of our
state and everything, we basically can change this into a functional component that just
renders the form. So maybe I'll go ahead and do that. That's pretty simple. And you'll
see that everything is showing up the same. And remember way back when I kind of talked
about how I like my app to be sort of a table of contents where I could put a header above
this and a footer below this and whatever main elements and then delegate the rendering
of those main UI components to the other components.
So our problem is essentially still the same
with form j s, because we still have one component that's doing all of this stuff. So what I'm
actually going to do is I'm going to create another component, this one we will call form
component, that j s. But essentially, you could call these whatever you want, you could
have form container dot j, s and form component dot j s, you can even put them into a folder
called form and make form j s actually just index j s and then have form component dot
j s, I've seen it done a bunch of different ways. And for clarity, right now, I'm actually
just going to rename form to form container so that it's obvious which one we're looking
at.
And that just means over an app js, I'll need to update this to form container. And
we're still working. Okay, opening the form container, I'm essentially going to take all
of the rendering logic, let's get this whole return statement. I'm going to take it out.
While I still have it in my clipboard, I'm going to go over to the form component and
create just a regular functional component. Thank you receive props. And let's paste our
whole return in there and fix some of our indenting.
Awesome. One thing you might notice
that's broken because we copied this from a component that was a class based component.
We have stuff like this dot State DOT first name and this dot handle change. Well, this
functional component doesn't have a handle change method and it doesn't have any state.
Instead, it's going to be receiving everything through props. So we'll come back and fix
this in a minute. But over on our form container, you now have an empty render. And what we're
going to do is let the form container delegate all of the UI stuff to the form component.
So at the top, I will need to import form component, the form component file, and simply
render a component. Like we said, we're gonna have to pass a bunch
of stuff through props down here. But already, we can see that my form is quite a bit simpler
than it used to be.
Okay, well, let's wire up our form components so that it has all
of the same information because it right now if I refresh this, you'll see that we have
some problems. And so what I actually need to pass are all of these properties in state.
And I also need to pass my handle change method. So let's start with the handle change method.
And I might as well just keep the name the same. That over in my form component. In props,
I'm receiving a prop called handle change, which means every time I have this dot handle
change, I need this to instead, say props dot handle change.
That's a good start. We still have problems
because we have no state in this component. So let's go back to the form container. And
I have a number of different options, the most annoying of which is I could pass down
first name, which is this dot State DOT first name, and then do this for every one of these
properties. But it's really that's pretty obnoxious, right? Because my form component
is now going to have maybe like seven or eight extra lines. Another option is I could just
pass everything, the whole state object down as a property called something like data to
the start state, this is leagues better than what we had just tried to do.
But it does
mean that in our form component, we're going to have, instead of this dot State DOT first
name, we'll have props dot data dot first name. And truthfully, that's not so bad. And
in fact, in my personal development life, I have tended towards this, where I pass an
object down and I just give it a name, it does mean that I have a little bit of extra
typing where I say props dot data dot first name, instead of finding a way to just have
props dot first name.
But as we discovered, when we were doing the travel form, screenbid
doesn't do so well with the object spread operator. But if you have the correct ECMAScript
versions supported in your project, you could simply say, pass down all of the properties
of this start state. Doing so would allow you to in your form component, say props dot
first name, props, dot last name, and so forth. Again, I have actually leaned towards sending
down an object, simply because it makes following the prompts a little bit easier for myself
in the future and other developers. But I've seen it used both ways. So it's really just
up to you here in screen. But I believe I'm going to have to do something like this. So
now let's go over to our form component and update everywhere it says this, that state
change this to props dot data.
Let's see if we have any problems, says nothing was returned
from render usually means a return statement is missing. Yeah, I think in my form container,
I Yep, I got rid of my return, which we cannot do. So we're gonna put the return back. And
we have one more error, it looks like it says that I probably forgot to export my component,
which Sure enough, I did. export our form component. And it says react is not defined.
And that's because I forgot to import react. And you might remember way back in the beginning,
the reason it says that is because JSX is normally not valid JavaScript. And so I actually
need the React library in this file so that it knows how to handle JSX. And our form is
backup. Let's see if it's working. Good news. Choose the destination. And say we have some
allergies or preferences and we're male. And yeah, it looks like everything else is working.
Perfect. And as such, we still have a quite large form that we have to scroll a little
bit in.
But this entire file is only caring about the UI component of our form. Whereas
over in the form container is only caring about the business logic of the form. This
way, we have a nice separation of concerns. And it allows us as a developer to essentially
have an easier time when we need to make changes to this file, we don't have to scroll up and
down over hundreds of lines of code. Now, one thing that's probably good to point out
now is with libraries like Redux. And with the recently released context API, notice
that the container component split of components here, like we just did is not actually used
quite as often, especially when you are injecting context or global state from Redux or something
like that into your components. When you do that, a lot of the business logic is delegated
to another place entirely. Which kind of means that you end up writing a lot more functional
components to simply consume the data that lives in Redux or in some global context or
something like that. But as you're developing your applications, this can be a really great
way to separate some concerns, if you find that you have a lot of business logic, and
a lot of display logic happening all inside the same component.
Hey, with that, under
our belts, we are ready to move on. Alright, we've made it to our capstone project, where
we're going to build the meme generator that we talked about at the beginning of this course.
Now, the way this will work is part of the time, I will put comments here that will give
you some direction for you to build out parts of the UI yourself, at which point like I
have in the past, I will give you time to pause the lesson and do that afterwards, we'll
go through that together. And there will be other times where I'm just building things
on my own and kind of explaining what I'm doing. Now notice that we're starting almost
completely from scratch, the only thing that I have included already is a bunch of styling
that I've pre written. And the reason I did that is because while this isn't a course
on styling, and just for time sake, so that it's not too boring, but over an index js,
we have nothing here.
So get excited, this is gonna be fun. And let's get started. Okay,
so the first thing you need to do is to create that boilerplate code that will get react
to render something on the screen. And the thing you'll render should be an app component,
which you'll need to create separately. Pause now and give that a try. Okay, let's
get rid of this comment.
And we'll say import react from react, React DOM, from react dash
DOM. We'll use react Dom to render our app component, which doesn't exist yet. We're
gonna put it at the root. we'll import app. And this is basically the
boilerplate we need for there. So let's create our app. Yes. There we will also import react from
react or export our component. Let's start by making a functional component called app.
Which we will have returned something so we can see that it shows up on the screen. Awesome. Okay, let me type up some
comments for the next thing that you're going to do. Okay, so you need to create two new components
header and meme generator, the header is only going to display things and the meme generator
will be calling to an API and holding on to data.
So let that information help you determine
what kind of component you're going to create. And as always, each of those components should
be in their own file of the same name. Pause now and try that. Okay, this one's pretty
straightforward. So let's create a new file called header dot j. s. And a new file called
meme generator. Yes, these comments are in the header import react from react. export the header. And since this is going
to be component that just displays things, we'll make it a functional component. Now, always I'll just put something that says header. And over in meme generators, since this will be
holding data and making calls to an API and so forth. This should be a class component.
We'll still need to import react from react and since it's going to be a class I'll go
ahead and just import opponent as well export the meme generator and create my meme
generator class that it will need a constructor which calls
super.
And I mentioned that it's going to hold some state. So I'll just put some empty
state there. And I will also put my render. So that as before I have something showing
up. Now that I've created both of those over in my app j s, I can import them. I'll go
ahead and use them here, I'll need to wrap everything in a single element.
We'll make an instance
of our header of our meme generator. Awesome, good so far. Okay, over in my header, I'm
just going to begin putting some stuff here. So I know that I
want to use the semantic html5 tag header. And I want this to have an image. And we will
set this as our source which is a troll face. And we'll give it an all property of problems.
too long for this line already.
So I will separated, we'll just have a paragraph that
says and I save this. Okay, you'll see my styles have kicked in because I used the header
tag. And I'm going to go ahead, I didn't do a great job making this responsive. So I'm
just going to make this window a little bit bigger. If that has overlaid your code a little
bit, you may want to make sure you maximize the window here, first grandpa and go a little
smaller probably. And this is everything we're going to do with the header for this project.
So we're going to go to meme generator, and pretty much everything else we do will just
be in this file. So now it's time for you to get your hands back on the keyboard. So
I will write up some comments here for what you're going to do next. Okay, we'll just take this one small step
at a time. So all you're going to do is initialize state to save the following data, top text,
bottom text, and a random image. And I've provided the URL to the first image that you'll
use.
So pause now and do this. It sounds pretty straightforward. So to initialize state, I'm
going to build up this object here and save top text, which is text, but I'll just start
it as an empty string. Bottom text, also an empty string. And my random image, which I'll
just say, IMG is the image I provided. They were not rendering this anywhere. So we can't
really display this. But that's okay. This is good for now. Let me delete these comments. Okay, I have
another challenge for you. Let me write up the comments now. So we're going to be using an API that provides
a bunch of meme images.
And your task is to make an API call to that API, which I've provided
the URL to, and save the data that comes back, which you'll find under response dot data
dot meems, to a new state property called all meme images. And the data that comes back
is going to be an array. Let's pause now and give this a try. When we're getting data that
we expect our component to have at the beginning, we're going to use the lifecycle method component
did mount.
As soon as the component mounts, we're going to use the native fetch function.
And we're going to call to the URL that I provided. And this will return a promise that
we need to turn into a JavaScript object. We will call the JSON method on that. Then
we'll get the actual response that will be useful to us. And I'm going to pull the memes
array from response dot data. And then like it says, we need to save it to a new state
property called all meme images. So I'm going to initialize that as an empty array, and
start, and then I will set state. And I don't really care what the previous state was. So
I will just say all meme images. Now B means that we just pulled just so I can see that
this data is here, I'm just going to console log, the first item in this meme, and take
a look at what that shows me. Cool.
So I've got an ID, a name, and a URL, which is what
we're going to be using is this URL property. Awesome. can delete these comments here, if
you remember back from the demonstration of what this meme generator will look like, there's
going to be two input boxes here that allow you to input the top text and the bottom text
on the image. So what I'm going to do now is just stub out a form. And then I'll have
you create the input boxes. So I'm going to wrap everything in a div building a form.
And for my styling, I'm going to give this a class name. informer. And we'll create a submit button.
It says
Jen, all right, and then I'm going to put some comments here for what your task is next. So now that I'm inside of my form element
in JSX, in order to write these comments, I have to put the curly braces. So that basically
tells the system that I'm back inside of JavaScript, so I can write these comments. So what you're
going to do, you can delete this when you're ready, what you're going to do is create two
input fields, one for the top text and one for the bottom text.
And remember that this
form should be a controlled form. So you'll need to add any of the attributes to these
inputs that you'll need in order for that to still work. Don't worry at this point about
creating your on change handler, because that will be the next thing that you do. So pause
now and try this. Okay, so this is just creating two inputs, so we will make two inputs. And
save time, I'm going to do this in both places, we will have a name attribute which one of
them is going to be top text. And the one is going to be bottom text. In both of these
should be a type of text, I will give them a placeholder. So I don't
need to worry about having labels. Take up text and say button text. And then for this
to be a controlled form, I need to make sure that I set the value equal to whatever the
current value of state is.
Up text, bottom text. Now the last part that I mentioned you'll
be doing next is to write the on change handler. And since these are both text inputs, you
won't have to worry about checkboxes or anything like that. So this one should be fairly straightforward
reference, let me write the comments up here. Create the unchanged handler method here and
it should make sure to update the corresponding state property on every change of the input
box. Pause now and do this. Okay, as I mentioned, this is going to be a fairly straightforward
one, we're going to have a handle change that will receive an event. And to fix my syntax
errors down here, I will add this to this dot handle change.
And that method will need
to be bound in my constructor. And while we're at it, I'll just put a console log here. See
if this is working. Let me get rid of that console log from the means console. And our
method is correctly firing. I want to pull the name and value properties from event target
so that I can get the name of state that I'm supposed to update top text or bottom text
and then whatever is actually typed into the box and I'm going to update my state. Now
I don't care about the previous state So I can just provide an object and I can say whatever
the name is it the value that we pulled from the box. Okay, and we'll get a chance to see
that that's working pretty shortly. If you want, you could pause now and there, right
a console log or put something in your render that shows whether or not this is working.
But we'll just move on.
Next thing I'm going to do is have a place to display our meme.
Now remember, we're receiving an array of all the memes that this API has. And what
we're going to do is make it so that when they hit the gen button, it just chooses one
of those images at random to display in the area below. So I'm just going to build the
area below right now. Make it a div. And for my styling, I give it the class name of meme.
Have the actual image here. source is going to be what we've saved in state as the random
image.
And I'll just put an empty alt property for now. And then for the text itself, I'm
going to have a couple of H twos which have a class name of up and bottom. And all they're
doing is displaying saved in state objects, text and text. Okay, so my image is showing up. This is the
random image that we initialized here. And let's see if my text is working. One does
not simply walk into Mordor and you'll notice that every keystroke, my text is showing up
correctly, which means I'm correctly setting the state on every keystroke. And the time
has come for you to do the last challenge of this Capstone. So let me write out some
comments. I wrote these purposefully a little bit vague
so that you had to think back and look at your notes or go back and look at previous
lessons, whatever it might take, going to create a method that when the gen button is
clicked, chooses one of the memes from our all memes images array at random makes it
so that image that it randomly chose is the one that shows up in our meme display image
area down here.
Now remember, the property on the chosen image in the array is dot URL.
You write that here. That URL is the property that is the string of where the actual image
is hosted. This is your final push, give that a try. Okay, so we could make it where I have
an onClick handler for my button. But because this button is inside of a form, I personally
think it's more semantic to have this be an on submit of the form. We'll call this handle
Submit. So this is where we will create that function. Need to grab the event, because
we don't prevent the default into try and refresh our page, which will be annoying.
So we don't want that to happen. And while I'm at it before I forget, let's bind the
handle submit in our constructor. What we have now is just a basic code challenge. Oh,
I will just pseudocode some of this, I'll say I need to get a random number, which represents
index the array and get the meme from that index.
Once I have that meme, I'm going to
set my random image property to the URL the random item I grabbed. I've broken this problem
into smaller parts, we're going to get a random number so that I can make sure that it's one
of the indices in our array. We'll make sure that I multiply whatever the random number
I get by the length of the meme images array. And now that I have that random number, it
should be easy to get a random meme just just the index of the all meme images Random number
that we just got. And all I'm concerned with is the URL property. So I'm just going to
snag that right now. And I just need to update state now. We'll use set state. I don't care
what it used to be.
And I know that I'm upgrading the random image property, and the value will
be the random meme image. Let's save this and see what we get. Oh, you'll notice that
some of these are funnier than others. But point is we have a random meme generator,
we've written the top text, the bottom text, it's randomly choosing from the array of images
that we pulled from the database online, we now have a completed meme generator. Just
because I'm OCD about this stuff, I'm going to get rid of these comments. This would be
a perfect time to check this code out, see if you can play with it make a better one,
be try to get the gist from a different API.
And although it sounds really obnoxious, one
of the best things that you can do to practice stuff like this is delete all of this code
and try it again from scratch. Feel free to take a break at this point, you've really
accomplished a lot of great things by following through this course and learning the things
that you've learned, I have just a few more topics that I want to cover before we finish
up this course.
Oh, as always, when you're ready, let's move on. Because react is maintained by Facebook, and
quite a few developers over at Facebook, as well as the open source community react is
progressing really quickly. If you've ever tried to watch tutorials of react from more
than maybe two years ago, you might notice that it's quite a bit different now than it
used to be. And we even had a lesson on how react version 16.3 introduced some new lifecycle
methods and also started the process of deprecating some other lifecycle methods will react 16.6
was just released. And there's even more new functionality now and a lot on the horizon
for react version 17 and onward. So I thought I would make this quick lesson about some
of the more modern features that you can use when you're creating react apps. And a lot
of these features will work or won't work, depending on which versions of ACMA script
you're supporting in your project.
But as long as you're using a transpiler, like Babel,
you'll be able to use pretty much the most modern versions of ECMO script and therefore
use some of these things. Now, I didn't do enough research to know which of these are
just experimental or which of these are definitely going to be included in reactor in JavaScript
in general. So you may want to just be aware that any one of these at any given point may
just disappear and not work anymore.
But it's pretty widely used. And I'm fairly certain
a lot of this will be included inside of either react or JavaScript itself. Now one of the
major changes is that our methods can be written as arrow functions. And I believe that scrim
that may complain a little bit about this. But if you're doing this in your own environment,
this should be okay. I can change this to be an arrow function, which looks like a very
small change. But in fact, what it does is it gives it a lexical this inside, which means
that it doesn't create its own this context, but instead uses the this of its surrounding
environment.
Basically, what this means is I no longer have to bind my methods in the
constructor anymore. So I could get rid of this. And because this is an arrow function,
and it's using the this from the class, everything should just continue to work. So that's a
really easy and convenient update that you can make to your class methods. Now, another
one that's a little more dramatic, but also really nice is the ability to create class
variables, just like we're doing here with this dot state. But doing so outside of a
constructor, so I can create this class property by simply saying state equals an object.
And
I guess in this case, to be consistent, we would have a first name, which is an empty
string. And doing this essentially allows me to get rid of my constructor entirely.
The last time I checked, this was still a proposal in JavaScript, but it looked like
it was heading towards being included into the language as a permanent resident. So I
haven't researched this recently, but just take this with a grain of salt and know that
again, this may not be included, but it's looking like it will be we can simplify this
a little bit, since it's just a one liner. So those are both really nice, fairly simple
changes that we can make.
I mentioned once again, the changes to the lifecycle methods,
I created a lesson that you've probably already gone through that talks about some of those
new lifecycle methods. So if you need a refresher, go back, watch those again. But Down here
at the bottom, I've included some resources to some of the more either advanced react
topics or brand new react topics. So for example, in react 16.3, they introduced a kind of public
non beta version of their context API, I've had a chance to play around with the context
API, and I'm a total convert. In fact, a Wii school, we have opted to drop Redux in our
curriculum, and OPT instead for using the context API.
And there's a number of reasons
to do so that doesn't mean that Redux no longer has a place. But for our purposes, the context
API does everything we want, and it's quite a bit simpler to learn. And then there's some
advanced react topics such as air boundaries, render props, higher order components. All
of these can be found directly inside the React docs, which you can see all of the links
here just go directly to the React docs.
And in fact, in the menu bar, they're all part
of an advanced react sub section, that would be a really great resource for learning more. I've also included here, a link to the React
router homepage, the React router is a great way to make single page applications using
a very declarative library, which is react router. It's very widely adopted and used
in most larger applications that are single page applications. Then, at the time of this
recording, these topics react hooks react, lazy, memo, and suspense are all brand new
additions to react. I haven't looked too much into lazy and memo.
But I know suspense has
to do with asynchronous loading. And hooks have to do with a way of essentially including
and modifying state in a functional component. And in fact, if you look at some of these
changes that react is making, it's looking like they're heading towards a place where
react will almost completely be written in functional components. And class based components
will not officially be deprecated. I think they even say in their docs that there's no
plans to remove class based components. But it seems pretty clear that they're moving
in a direction that they are encouraging the use of functional components more and more.
Hopefully, I'll get a chance to update this course, to include some more topics as they
become released. And as I become more familiar with them, but for now, just know that react
is changing constantly.
And it's always a good idea to be checking the change log to
be engaged in your community and watching for these changes, because it can be really
beneficial to you and your career to be up to date on the most advanced and most modern
react features. So we just went through and created the meme
generator together. And before that, we had done a multi part series on creating a to
do app, but to do apps, honestly, are pretty boring. And the more you do them, the more
boring they get. And so I decided to include here some resources that you might use to
come up with ideas for apps that you might want to build yourself, I was going to come
up with a list of my own ideas. And then I came across Free Code camps lists that they
have built over the years. And each one of these is an entire blog post with a whole
bunch of different ideas that you can use. So I would honestly just recommend visiting
these websites, reading through the ideas that they have, and either picking one or
using that as inspiration for ideas for you to come up with.
Alright, you've made it. Now there is so much
more to learn about react. But you now know all the building blocks, you need to start
building react apps for yourself. So let's look at a quick summary of the core concepts
we've talked about in this course, we talked about JSX, and how it's a wrapper around JavaScript
that allows you to write your UI using a familiar syntax. html, we noticed that there were a
couple slight differences here and there. But for the most part, it helps writing components
feel very familiar. We talked about two different kinds of components that you can make a functional
component and a class component and what each one of those is capable of. Basically, if
you need state or lifecycle methods, you will have to use a class based component. Otherwise,
it's a pretty good practice to just stick with a functional component. In fact, going
forward react is kind of looking like there'll be releasing features that allow everything
to be written as a functional component if you want.
We talked about some basic ways
to style react. If you're using CSS classes, you'll need to use class name inside of your
JSX in order to assign a class to that element. Or you could write your CSS as a style object
directly in your JavaScript, which can be helpful if you need them to be dynamic, or
you just generally prefer to style right there inside your component. We talked about props
which are the primary way to pass data down the component tree and we covered state, which
allows your components to hold on to and modify the data.
Anytime you want to change state
you'll need to use these sets The method, we talked about conditional rendering, using
various vanilla JavaScript techniques, you can determine which parts of your UI you want
to show up at any given time. And oftentimes, this is done based on some variable that's
held in either state or props. And we spend some time learning about forms in react and
how to gather input from users in form elements.
And there is so much more about react that
I would love to cover, but we're going to have to save all that other good stuff for
another course. For now, thanks so much for letting me guide you through learning one
of the best frameworks out there..