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.