TEDDY LIU: Hi guys. My name is Teddy and this is my seminar
on Frontend Development with React. So let's just get started with it. So first, what is React? So officially on their website
it's a JavaScript library for building user interfaces. But more unofficially,
colloquially, it's a dope JS library that makes it really
easy to build responsive web pages. So this was originally
developed by Facebook and its rival is Angular JS, which
has been developed by a rival company Google. But we're going to
talk about React today. So some things that I'm going to
assume is one, only one thing, it's like you have a basic, very
basic understanding of JavaScript. And if you have a familiarity
with any programming language, this should be pretty simple. So some things that I'm
not going to assume. I'm not going to assume that
you have Node and npm install. I'm not going to assume that
you're familiar with ES6 syntax. I'm not going to assume
that you have understanding of object oriented programming
or functional programming. And I'm not going to assume that you've
created a dynamic web site of any type before using JQuery, Angular, etc. OK. So some key takeaways from the talk
today is how to actually get started, something called JSX,
which we'll get into. Components along with
their props and state. The render method, the Virtual
DOM, and functional components. And also at the end I'll talk a
little bit about the next steps after you learn the material
from today's seminar. OK. So how to actually get started. And I wanted to focus on this
because I think a lot of tutorials tell you how to do something inside like
a browser or inside a pre-built editor but no one is actually telling you
how to create something and get it running on your personal computer. So I wanted to focus a little bit
on that at the beginning today. So first you're going to
want to install Node and npm. And before, just the disclosure,
use your own computer. Don't run this on CS50 IDE. Eventually you're not
going to support for that or you're not going to be
allowed access to that anymore. So you're going to want to
run this on your own computer. So first Node just allows us to
run JavaScript on our desktop. Usually it runs only
in our browser, that's what Google Chrome and all those
other browsers are capable of doing. But Node lets us do this
on our personal desktop. Npm stands for Node
Package Manager and this lets us install useful things that
people have created over time written in JavaScript, intended for Node. And you can find them
here at this link and I'll make sure that these slides are
shared afterwards with people. And for right now install
8.9.0 long term service rather than the newly released
9.0.0 since React is only supporting Node 8 at the moment. OK. Once you have those
two things installed, we're going to install something
called create-react-app and this is exactly one
of those npm packages that I was talking about earlier. And so it's really easy to install. Just go to your command line and
type these commands npm install. This -g is saying globally,
so this is for all users. And then create-react-app. And this is just a tool
that was created by Facebook to help you actually get started faster
without doing all the initial grunt work. And then finally, we're going
to create and view the project. So we're going to type
in our command line again create-react-app react-seminar. This is going to create a folder
and install the necessary packages in that folder to be able to run React. And then we're going to cd into
that folder and type npm start. And this is going to
launch a local server. And we're going to go
to localhost 3,000, if that's not automatically redirected. And then you're going to
have your first React app. So let's go do that right now. So here I'm going to type-- So I've already created
the folder ahead of time since I didn't want to
spend time downloading things just so that you can see. So I'm going to cd into react-seminar
and I'm going to type npm start. And this is going to be starting
a local development server. And you'll notice that I've opened up
that browser and on localhost 3,000 here, I already have a dynamic
web site available to us. So congratulations
you've gotten started. OK but now let's actually
try and dig into the code. So if we go into Sublime
Text here and we open up the code that was generated
inside this react-seminar folder, we're going to find a lot of
different things on the side. But most importantly, we're going to
want to look in this source folder. And inside the source folder are
going to be a bunch of different files but the most important of which
is going to be act.js here. And let me just change
something really quickly. And we're going to be confronted
with a bunch of JavaScript code and right now, it's
going to look foreign but we're going to talk
about this in just a second. So going back. So let's start digging
into the code here. So what we just saw on the
screen was something called JSX and usually we develop
with JavaScript by itself. But JSX is like JavaScript
extension and what this essentially lets us do is mix JavaScript and HTML. So whereas normally we
would only be allowed to assign variables and return
like integers, strings, lists, those standard things. In JSX we're allowed to return HTML
tags like divs, buttons, inputs, all those things. And when we return those things,
they'll be displayed properly inside the web page. Another thing that we'll see is
something called the component. And this is the fundamental
building block for React. So these components have internal
state and external props, we'll talk about what
those things are later. And these are nested
inside of each other and can be used across multiple files,
and even across multiple projects. And so this component is like
a contained view of the project and we're going to be changing
the way this component is rendered based on the internal
state and external props. So talking about that state,
the state is within a component and it contains this internal
information about components, the stuff that we're going to be
changing dynamically. And we have some initial
state, most of the time, and we're going to change this state
instead of directly modifying it with a function called this.setState. And I can talk about the
importance of this later. And then finally, there's
a method called render, which every component must have. And this is called
whenever the state changes. And here is where we decide
what the user should see based on the current state and the props. And even though whenever we change
the state we're calling render, not everything is getting
re-rendered to the page or the DOM. And this is because of something
called the Virtual DOM. And what's happening is render
is changing the virtual DOM but React is doing
extra work for us to be able to compute the most efficient
way to change the actual DOM on the web page, such that your pages
are loading really, really quickly. So with that, let's start
testing a little bit, playing around with a bit of the code. So the first thing we're going
to do is in this app.js file, we're going to delete pretty
much everything inside and just start from scratch. OK? And so notice that we have something
called app and an extends component. This is saying that we're
creating a new React component. And notice that we're
also exporting it such that other files can import this
app component and use them directly. So one of the first things that every
component needs is a constructor and we'll declare it just like this. And inside this constructor, we're
going to want to first call super, this is what allows us to use
the keyword this in JavaScript. And confusion about this is pretty
common, but I won't go into that right now. And then we're going to want
to set our initial state. So in this example, I'm going to
create some kind of trivial application where I'm going to have a
button and then a number. And as I click the button, it's
going to increment the number by 1. And I'm just going to
keep clicking the button and it's going to keep
incrementing the number. So it's a pretty trivial application but
it shows a bit of the power of React. So to set the initial state, we're
going to say this.state equals. And then this.state is going to be a
dictionary or an object in JavaScript. And so I'm going to have
something called the count and it's going to start with values 0. So that's the constructor. We've set up everything we want
initially this component to display. Now we need to create the render
method that I spoke about before. So this is the same thing. So in the render method
we're going to want to return HTML that we want
to be displayed on the page. So we're going to return in this
fashion and we always put parentheses to group things together properly. And we're going to return a div. And inside this div we're
going to return a button. And then here, just like we would
do in GINGA, if you're familiar, we're going to be able to inject
the actual code values into the HTML element. So here we're going to use the brace. And this is saying
that we want to access something that's a JavaScript variable. And we're going to say this.state.count. So we're just going to put the
count directly inside HTML. And then finally with
this close this div. So if I save this-- If I go back to the
HTML page, we'll notice that it's a little uglier than before
but we now have the two things that I wanted in the first place. We wanted an increment
button and the number zero. But right now, when I
clicked the increment button, nothing's happening because I
haven't defined any behavior for what happens when the button is clicked. So let's do that now. So when we click the button
we want a method to be called, some function to be called,
which increments the count. And to achieve this
we're going to create a new function within our
component and we're just going to maybe call it increment. And here I'm going to use
something called arrow notation. And what this is essentially
doing is creating a new function, which takes in the
parameters that I'm going to specify. So in this case, it
takes in no parameters. And then I'm going to draw this arrow. This is saying this
goes to this code block. And then just use it
like a normal function. Some advantages of this is that it
preserves this, like this or this. And if I had done it
in the traditional way, like I did with the
other two functions, then this would actually
be the function itself instead of the overall component. The specifics of this
aren't exactly important, so I'll gloss over them for now. But just know that using this arrow
notation will save you some headache in the future. So in increment, we want to be able
to update the count of the state. So we might be tempted to just say
this dot state dot count plus plus. But because of the way
the React functions, and it's always computing this optimal
difference between the virtual dom and the actual dom, we want
to do this in a functional way such that we're creating
a pure copy of the state. So instead, we're going
to say this dot set state. And this is a function
that takes in a dictionary. And we're going to specify
which fields we want to change. So we're going to set the count to now
be this dot state dot count plus one. Now that we have this
increment function, we still need to put it
on the button itself. So the button has a
property called on click. And this takes in a function
that we're going to specify. And again, we're going to use
these special braces, such that we know we're injecting something
directly from the JavaScript instead of an actual string here. So we're going to pass in
this increment function. And this increment is a method
of this, or the component itself. So what we're going to do is we're
going to say this dot increment. And now if we go back to our
page, when we click the button, we notice that the number is
in fact increasing every time. So this is a really trivial application,
but I think it shows and highlights the powers of React,
because we notice that even though I'm clicking increment,
and we're calling this render function every single time,
the button is not changing. So what could naively be done
is we could rerender the button, and we render the text every
time we click the button. But instead, we noticed that
only the number is changing. And this is React, again, doing
that efficient computation to compute the exact difference that
it needs, such that the difference is as fast as possible, OK? So that's this very trivial example. But I wasn't here to just show you how
to create cookie clicker from scratch. So let's jump into a more complicated
example, creating a todo application. So again, we're going to
want to scrap everything that we've done so far because
we don't need this anymore. So we're going to do is
we're going to start over. We'll just delete all of this,
and just start from scratch. So, again, we're going to need
a constructor for our app. And we're going to call super again. These are just things that we have to
do every time that we have a new React application. But now our state is
going to be different. So I'm creating a todo list. And a todo list is essentially just
exactly that, a list of todo's. So the state should hold
all that information, all the todo's that we've added so far. So what we can do is we can
say this dot state equals. And then we just have todo's. And this is going to
start as an empty list. So that's going to be our state. And then in render, we're going
to want to return those todo's. And also, we're going to want to offer
a way for the user to input new todo's. So we'll have an input for them,
and we'll maybe put a placeholder. And we're going to have a
button for them to be able to-- sorry about this. We're going to have a button for
them to be able to add the todo. And then finally, we're
going to want to have a list of todo's available for them. So right now, we're going
to gloss over this step. We'll come revisit it again. But because of React's nice
syntax, we can actually put some conditional rendering here. So we can check using the
ternary operator in JavaScript and the ternary operator
in all languages whether this dot state dot todo's
dot length is equal to zero. And we're going to
ask, is it equal to 0? And if it's not-- if it is equal to
zero, then let's return the string. No todo's yet. And otherwise, we're going to return-- you still have some todo left, OK? And let's see what
this renders right now. So OK, we're having some problems here. Let's see, no todo's yet. Oh sorry, I forgot to put
a closing tag on this. OK, so we have a crude todo
method, or todo list app now. However, we've typed something
here, and we click the Add button. Again, we notice that same
thing, that nothing is happening, and furthermore, that
this is not changing. But notice still that this says no
todo's yet instead of you have some todo's. So we have some logic going on here. And that's just highlighting a
little bit of the power there. So now I'm going to start moving
a little bit quicker since I don't want to run out of time. So just to clean this
up just a tad we're going to add a break here so that
the todo's are in the next line. So in this input, we want to hold the
next todo that the people want to add. So that's also a part
of the state, actually. And we want to include
this in the state. So what we're going to do is
we're going to say current todo. And this is going to be just some
string, initially the empty string. And we'll let the value of this input
be this dot state dot current todo. Now, if I go back to the
application, and I now try and type, I'm hitting the keys now,
but nothing is showing up because the state is not changing. So the input, the value of this
input is being bound to a state, and that state is unchanging. So now we need to add a new method here. Sorry about that. So we need to add a new method
here such that when this is changed we are actually changing
the value of the state. So we're going to add it on change. And this means that we're going
to need to declare a new function. So on change is this going
to trigger a function and pass in something called an event. And this event essentially tells
what the input was changed to. This is very specific, but we'll
say on input change equals e. So this is taking in an event. And, again, this is bringing up that
es6 object or anonymous function definition. And we're going to say, OK,
so this dot set state, again, calling that set state function. And we're going to say current todo
becomes e dot target dot value. And so we're going to pass in
the same function down here. And now hopefully when we
change the value of the input, we'll see that, in fact,
OK, my typing is showing up. So now all we need to do to actually
get some todo's to show up down here, or maybe to change this no
todo's yet, is to implement some functionality on the Add button. So, again, we're going to
want to declare a new method. And here, we're going to see
something about, again, not doing pure changes to the state
instead of mutative changes. So we're going to say on click. This is just going to be a function
that takes in no parameters. We're going to want to create
a new list of todo's, which is the old list with the new
current to do appended to it. So we don't want to actually
modify the list in place. Instead, we want to create a copy. So we'll say todo's copy is equal to
this dot state dot todo's dot slice. And this will create an exact
copy of the original todo's list. Then on the todo's copy,
we're going to want to push this dot state dot current todo. So this is adding the new todo
to the end of the todo list. And then finally, we're going to
want to set the state properly. So we're going to say todo's is
going to become the todo's copy. And we're going to want to clear out
the old todo or the current todo. So we're going to stay current todo
becomes the empty string yet again. So now if we pass in this
function on click to the button, and we say on click
equals this dot on click, we're going to see something happen. So we're going to enter a todo
here, and we're going to click Add. And notice that we haven't
exactly displayed it, but now this has triggered
some change in the state. And this conditional rendering is taking
care of something behind the scenes. And we're starting to see the
hint of something actually dynamic going on in our application. So let's continue on this trend. We have a bunch of todo's in our state. We just need to decide how
we want to display them. So I think a natural way to
display them is to create an unordered list, a bulleted list. And so we'll do exactly that. So in this render, we're going to
say we want a list of all the todo's. So we can do this by
doing a JavaScript map. And we're going to say
let bulleted todo's-- it becomes this dot
state dot todo's dot map. And map is going to take
in an element and an index. And it's going to return something. And now here, again, we're going
to see this combination of HTML mixed with JavaScript. So we're going to, for each
element, return some kind of JavaScript or HTML element. So we're going to return a list,
and we'll let the value be e, and then we'll just
close the list element. And furthermore, when we do loops
like this and React assisted with this computational
difference, we're going to add something called the key. And the key can be anything as long
as it's a unique per-iterated item. So in this case, I've chosen the i to
be just the index inside this list. And then finally, we're going to
want to inject this into the state. So here, where before I said
if there are todo's then we'll see you still have some todo's,
I'm going to change this to become UL and then followed by
bulleted todo's, OK? And then we're going to see-- so now if we add, we're
going to see that now we're adding things to the element. And notice again, that this is a
rendering in exactly the way you would hope it would, such that when we
add new todo's another thing to do, this is efficiently
calculating the things that we need to do between each render. So even though I'm rerendering the
whole page for the virtual dom, it's only appending exactly
what the differences is. It's only appending the new todo. It's not redoing the whole entire list. So if I add a bunch
of these rapidly, it's not going to recompute
the whole entire thing. So that's, again, hinting at
the power of what React can do. But I feel like this todo application
is still missing some things. And that's the ability to delete
things that we've already added. So again, this is a
trivial functionality, but maybe we want to add it. So first, visually, how can we add this? So instead of in each list element,
we can just say have a button. And it just can show the value x. And now this is going to
show an x next to each thing. So if we-- supposedly,
ideally we would want this to delete it when we click the x. Of course, that functionality
hasn't been implemented yet. But now this is starting
to get complicated because each list needs to-- each list element
needs to have a button. And this button needs to
know which thing to delete and when it needs to delete it. We need to know how to
delete it from the state. So this looks like a good
opportunity to create a new component, a new component
to nest inside our larger app, such that this makes the
development a little easier. So we'll do that as well. So we can go back to our
folder in the command line. And if we create a new
file in the source folder-- and we can call it single todo. And we go back. And now we can-- again,
in our search folder, we'll see that this has been created. And this is a good chance to
create something from scratch and just see what exactly is going on. So let me quick make a quick change. So with every React
component-- and I should've mentioned this at the beginning. But we need to import React
and the component from React. And what this is doing is-- importing React itself lets us
type in this JSX style language, this mixture of JavaScript and HTML. And then the component is what lets us
create a new app, or a new component. And then we're going to have to create
a class much like we did in here. So this was called class app. And it extends component. And we're going to do
the same thing here. We're going to create a class single
todo, which extends component. And we're going to do the same thing
here where we create a constructor. And we don't actually need to
do anything, because everything that this component has, we're going
to be passing down to it via something called props. And so props are different
than state because state is internal to the component, whereas
props are passed in from the outside. And we'll see how exactly
those are passed in later. And then, of course, this
needs as well a render method. And so the same thing can happen. So we can just return. And for now, we'll just
do something similar to what we did above, so a list
element, but instead of e now, we'll just say this dot prop dot todo. And we'll have a button, which for
now, again, just shows the thing x. And then we'll finish the list element. And then finally, for this to be
able to be used in other components, we're going to want to export this. And so we're going to say
export default single todo, much like we did in-- again,
this is very similar to how we are working in app dot JS. So now that we have
created this new component, we're going to want to import it inside
of our other larger component, the app. So how are we going to do this? The syntax is as follows. At the very top, we're just going
to say import single todo from, and then we'll say
dot slash single todo. And what this is doing is it's looking
in the source folder on the left here, and it's looking for something
called single todo dot JS. The JS is optional. And it's going to import exactly what
we exported by default, the single todo. And now inside of our
render, we can call this. Instead of returning in
this map the list element, we can just return a single todo. So essentially, by
creating this component, we've created ourselves
a custom HTML component that we can parametrised in
exactly the ways that we want. And so now we can pass down
this thing called a prop. And notice that this
prop is called to do. And so what we have done
by giving it this prop is we can pass in something
called todo, and we can give it exactly what we want. And then we can close this and return. So I haven't added any additional
functionality, but what I've done is abstracted away the features of
this component into something else. And so, OK, I have a
compilation error here. So it's advising I put
super, and I will do that. OK, so now we're back to
our original application. And again, if I add something-- it's saying this dot prop. Sorry, my apologies. This should be props not prompt. So if I go back here-- OK, so we see that we've achieved,
again, our original functionality. And we're going to now want to
pass in also a function that this-- we're going to want to
pass down a function that this can use to achieve
the deletion that we want. So in our top level app, we're going
to let the state of this application be the single source of truth. So this top app is delegating
everything and every bottom, every component that's nested within it. So here, we're going to
say delete todo, and this is going to take in the
index of a todo to delete. And again, we're going to want to create
a copy of the current list of todo's. And so what we're going
to do is we're going to do the same thing as we did before. And then we're going to want to delete. And this is just a
JavaScript syntax thing. But we can do this by
doing splice i comma one. And then we're going to set the state
to be this new list of todo's, OK? Then we're going to want to be able to
pass this down to each of the smaller single todo components. So on this buttons click,
we're going to want to just say this dot props dot delete. And this component has no
idea what this actually does. But the global component,
the parent component is going to tell it
exactly what it should do. So now we're going to pass in a
function or a prop called delete. And this prop can be
whatever we want it to be. So in this case, I'm
going to create it to be a new function, an anonymous function,
such that when this is deleted, it's going to trigger
this function, and this is going to call this dot delete
to do with the variable i, because i is the current
index of this, OK? And so now, if we go back, and
we add a todo, and we add it, and we click the x, we notice that
it's now been deleted properly. And so if we say something to do,
something else, something thrice, we can delete them one by one
in whatever order we want. And again, these are just triggering the
things that we're passing down to it. And this is, again, I'm trying
to express the power of React. But it's just this declarative
way to describe the user interface that you want. So at any point, I'm just telling
exactly what I want to be happening. OK, so one last thing on
this single todo component, notice that this has no internal
state because everything about this is determined by what the
parent says it should be. And so instead of creating an
actual class, we can do something called a functional component. And instead of creating a class,
we'll now create a function. So we can say const single todo. And this const keyword is, again,
just another feature of JavaScript. It just means that
this cannot be changed. And it's going to take
in only one argument. And that's the props. And then instead of
doing a Render method, it just simply returns
exactly what we want. And so if we just copy/paste this
line, and we comment out this, then again, we're going
to get the same behavior. OK, oh, yeah, sorry. So now because we're passing in the
props as this argument to the function, There's no need to say this anymore. We can just call the props
directly because the props are readily available to us. And they're not a property of this,
but they're rather just an argument passed to this function. So we change this, and
we try again, we'll now see that we have all these various
things that we can delete, add, and so we have in just the course
of 20 minutes, created from nothing a todo list in React. And so now just to wrap things up, so
we created this simple todo application. And in the process, we learned
about a couple of things. So we learned about the props. And these, instead of
internal state, like something managed within a component,
they're passed from the outside to the component. And we see that by
creating this component, we're essentially creating a custom HTML
tag that we can parametrise in any way. And the component in
general should not be able to change the
props that's it's given. And also, we've seen these functional
components, which only accept props and they have no internal state. And in general, we want things to be
as pure and as functional as possible. We want to have only a
single source of truth. We don't want to have multiple
things with multiple states and they can be in disagreement. Instead, we want to have
a single source of truth, and then that delegates what
everything else should look like. And React will handle
all the rendering again. So some next steps--
so this is, of course, a very, very, very simple application. But there are limitless things
that you can do with React. And Facebook and a
lot of other companies have been exploring
exactly these avenues. So something else to look
into is called Redux, which is a global state container. And this is achieving exactly
what I was describing before, this single source of truth. So instead of having
different components managing different parts of the state,
we just have a single container of all the state. And a particular component
subscribes to a part of the state. And this is passed down to it as a prop. And also, we can look into
something called React Router, which allows for things called
single-page applications, where the URL is dynamically
changing, but the page itself is actually never refreshing. And so this has huge implications
about how web pages can load and how when we go to
different web pages, we don't actually have to
rerender the whole web page, we can only change the part
that is actually changing, OK? So if you have any questions,
you're free to ask them right now, or you can reach me at my email. This is my email here. Send me questions about my
seminar, send me feedback, but this has been an introduction
to front-end development with React. And thank you very much listening.