[MUSIC PLAYING]
SPEAKER 1: OK, let's get started.
Welcome back, everyone, to CS50 Beyond.
So for a little bit of context
from where we've been so far--
thus far in CS50 Beyond, we've mostly
been building on a lot of the topics
that we saw in CS50.
We saw each HTML.
We saw CSS.
We saw JavaScript.
We saw a SQL.
And we've been taking those ideas so far
this week and just building onto them,
showing you some additional features,
some more advanced capabilities,
building some more
sophisticated applications.
Today we're really going to
introduce something entirely new--
that being React, which is a JavaScript
library built by Facebook, which
is designed to make it very easy to
build interactive and dynamic user
interfaces.
And React is going to be a totally
different way of thinking about
how to build web applications,
and how to build user interfaces.
And we'll go through a bunch
of examples to give you
a sense for how this works,
how to think in React,
and ultimately, how to program in React.
And so, React has a couple of key
concepts-- a couple of key ideas
you want to be thinking about.
And the first of those
ideas is that React
is a declarative way of programming.
And so, thus far in most of what we've
done in CS50 and in programming more
generally, we've been doing what you
might call imperative programming.
In imperative programming,
we write code that
tells the web application what to do.
We want to insert this
thing into the web page.
We want to manipulate the web
page in this particular way.
But whereas imperative programming
is a model where we say,
this is what we want the
web application to do,
declarative programming is a
style of programming where we say,
this is what we want the web
application to look like.
This is how the application should look.
And we're going to let React
take care of figuring out
what the application should do
in order to make the application
look like the way that we want to look.
And you'll see in a moment
what that actually means,
and what it actually looks like.
So that's the idea of
declarative programming.
And in order to achieve that
goal, there are a number
of tools that React is going to use.
The first of which is that,
instead of using JavaScript,
it's going to use a slight
extension to JavaScript--
a variant on JavaScript that has
a few more features-- called JSX,
or JavaScript X. And the idea of JSX is,
whereas in JavaScript we have a whole
bunch of different types of values--
we have integers, and we have strings,
we even have functions
and arrays and so forth--
in JSX, we can treat each HTML
elements as values of their own.
So in JSX, you might see code
that looks something like this--
const, some variable name, equals,
and then an h1 block, for instance.
Like HTML code that can
be a value in JavaScript
that we can assign to a variable,
that we can loop over at some point,
potentially, that we can do
calculations and computations on.
This sort of code is common in
JSX and has some special meaning.
So that's something that we'll
see in React in just a moment.
And so in order to make this
work, there are a couple
of libraries that we're going to need.
I'll just briefly
describe what they are,
and then we'll actually
start using them.
React is going to be the library
that's going to actually allow us to do
the building of these user interfaces.
There's a separate but related library
called ReactDOM that's going to take
care of taking the React
components that we create--
more on components in just a moment--
and actually inserting them into
the web page, into the DOM--
the document object model.
And then finally, we're going to
be using a package called Babel.
And we're using this
because most web browsers,
in fact, all of our modern web browsers
don't understand JSX code natively.
So code that looks like
this, Chrome and Safari
don't normally know how to understand
this code and figure out what it means.
So what we need to do is
translate this sort of code
into regular JavaScript code
that our browsers can understand.
And Babel is going to take care of
doing that translation for us, such
that the browsers can actually
understand the code that we're using.
So in a moment, in our HTML
pages, in the head section
where we might include
JavaScript, we're going
to be including a whole bunch
of scripts-- one for React,
one for ReactDOM, one for Babel.
You can just copy these scripts and
put them at the top of your HTML page.
And you'll see in a moment how
that will eventually become useful.
So all of React is really designed
around this idea of components.
When we're going to think about our
web application, we're going to try
and divide the application
into the components
that make it up, and
then start to analyze,
how is that component going to behave?
And a component is going to end up
looking a little something like this.
If we wanted a component that
was just going to say "Hello",
we're going to define a class
called "Hello" in JavaScript,
and extends React.Component
is basically just saying
that this Hello class
is a React component.
And what do we do from there?
Well, each React component
needs to have some notion of,
what does it look like when I
render this component to the screen?
When I try and take this
component and display it
on my web page, what should show up?
Declaratively, what is going
to show up on the page?
And so, every component is
going to need a render function.
And that render function is
just going to describe what
it is that this component looks like.
And in this case, this Hello
component, very simply inside
of its render function, is just
going to return a JSX element
from HTML like code, that it's
just a heading that, in this case,
says "Hello".
So we've defined a react component.
This is our first React component.
And all it does is display an h1 tag.
So I'll show you that right now.
We'll actually build our
very first React application.
So I go into a code
editor, create a new file.
I'll call it "hello.html".
All the source code examples
for today are already
online if you want to
take a look at them.
So let's say, DOCTYPE HTML.
In the header section
of the website, I'm
going to need to include
those JavaScript libraries.
I need to include React
and ReactDOM and Babel.
And so I'll go ahead and
go back to these libraries.
I can just copy these scripts
and paste them into the page.
I'll give this a title as well.
We'll just call it "Hello".
And now in the body
of the application, I
need to create a space inside
the body of the application
where my React application
is going to live.
And so I'm just going to create a div--
some vertical section of my page where
I'm going to insert my application--
whose id is going to be app.
And it's just going to be an empty div.
Nothing inside of it.
This is where my
application is going to go.
And now, let me add
some JavaScript code--
some JSX code that's going to render a
React component inside of my web page.
So I'm going to use
a script tag, but I'm
going to use a special type attribute.
The type is going to be text/Babel.
What this is basically going to say is
that this is not regular JavaScript.
This is JSX, that special
version of JavaScript
that I mentioned a moment ago.
And the fact that I'm labeling
it with "type text/Babel"
is going to tell Babel the package that,
OK, this is JavaScript code that I'm
going to need to translate
into regular JavaScript
before the browser is going
to be able to understand it.
So when we open the page,
Babel is going to first take
the step of translating it for
us, so that Chrome or Safari
or whatever browser you're using
can actually understand this code.
So now, let me go ahead and
define my first React component.
So we're going to call it class
Hello extends React.Component.
So I've created a React component.
And remember, the one thing
that every component needs
is a function called render that's going
to say, what should this component look
like when I render it to the screen?
So I'll define a function called render.
And what this function
render is going to do
is it's going to return something.
And it's going to return, let's
say, in h1 tags, the word "Hello".
This return statement-- I've enclosed
the whole thing in parentheses
just in case I need the
HTML to span multiple lines.
It's not really necessary
in this case, but you'll
see this pretty commonly as you begin
to build larger and larger components.
So all the Hello class
is doing right now
is defining a component that
describes what it should
look like when it's on the screen.
Questions so far?
All right, the next step,
and really the last step
of building this particular
application, is just saying,
I actually want to render
this component on the screen.
And so, in order to do that,
we're going to use ReactDOM,
which is that library that
lets us take React components
and put them into the DOM into our page.
And we're going to say ReactDOM.render.
And ReactDOM.render takes two arguments.
The first argument is, what is the
component that we want to render?
And the component we
want to render is Hello.
And now you can treat Hello just
like you would treat any other HTML
element for example.
I'm just going to say, Hello as
though it were an HTML tag like div,
or h1, or some other tag.
Because I have defined
it as a component.
And so now I can just say, I want to
render the Hello component in my page.
And where on the page
do I want to render it?
Well, I want to render it here.
In other words, the section
of the body that has id app.
And as we've been doing
previously in the week,
if I want to get at that particular
part of the page, I can just say,
document.querySelector("#app") to
say, get the thing that has id app
and insert this Hello
component into the page there.
So I'll show you what it
looks like, assuming this
all works, and then we'll
go back to the code.
I'll open up hello.html.
And all right.
It just says, "Hello".
It displays that as an h1 tag.
And the way it did that is because
I took this hello component
and rendered it into the DOM.
So in 28 lines of code, we've
defined our first React application.
What questions you have?
All right, so let's move on a little
bit and look at some more things
that we can do here.
So we have this class called
hello, this can React component.
And once I have a React component,
I can reuse that component.
I can use it multiple times if I
want it to do different things.
And so, let me to find
a new React component.
I'll call it "app" that's going
to extend React component.
And the render function
of this app is just
going to say when you
render this application,
go ahead and render a div, inside
of which are two hello components.
You can nest components within
each other, so to speak.
So inside of my app now,
I'm saying, let's render
two hello components,
one after the other.
And inside the DOM, let's go ahead
and just render the app component.
So I'm rendering the app component.
And what does the app component do?
It renders two hello components.
And each hello component is
just going to say "Hello".
I refresh the page.
And OK, now I have two hello components
that are displayed on the page.
Questions about anything so far?
I'll go back to the code
so you can take look at it.
All right, so this is
the basics of what React
is about-- defining these
components, and then defining
what the page should look like,
and then letting that render.
Though so far, all we've
done is render something
that we could have done much more
easily with just HTML and no JavaScript.
So let's take a look now
at what we want to happen
if we want different components
to behave differently.
Maybe I don't just want hello
to say just the word "Hello".
Maybe I want it to say hello to
a particular person, for example.
And so maybe I would like
to add some attributes,
or what we're going to call props
or properties to these components.
And so I want to say hello
to a particular person.
I'll pass an argument, or a prop, to
this hello component-- name being Josh,
for example--
and another prop whereas
the name is Athena.
And maybe I want more hello components--
one where the name is Julia,
and one where the name is Krishna,
and we'll do one more for Andrew.
So now I've got five
different hello components,
each of which I'm providing
some different information.
I'm providing in a name, a
prop, into the hello component.
And now inside the hello component,
I'm going to use that information.
Rather than just say "Hello", I'm going
to say hello to whatever the name is.
And so, in JSX, this type of syntax--
if I want to plug in some value here,
I'm just going to use curly braces.
And in order to get at this component's
props and get at the name property
of those props, I'm going
to say this,props.name.
So the hello component says
"Hello", and then in curly braces,
let's plug in this.props.name to get
the name property of this component,
and plug it in there.
And then my application
is just going to render
a whole bunch of hello
components, each of which
is provided with a different name prop.
So I go ahead and refresh the page.
And all right, great.
I see five different
components, each of which
now behaves differently based upon
what properties it was initially
provided with.
Questions about anything so far?
Yeah?
AUDIENCE: Could you use Jinja
[INAUDIBLE] difference between
[INAUDIBLE]?
SPEAKER 1: Could you use Jinja?
So Jinja is a templating language.
You couldn't use Jinja
in just this HTML page,
because you'd need some sort of
renderer that actually processes Jinja.
But you could imagine combining
Flask and React together.
And there are certainly ways
to do that if you wanted to.
Other things?
Yeah?
AUDIENCE: Was name an arbitrary value?
SPEAKER 1: Yes, name was
just an arbitrary choice.
You can create props of
any name that you want.
You can call them whatever you
want, so long as you're consistent.
The only thing that matters
is that this name of the prop
here matches up with
this name here, so that I
can reference the correct property.
Yeah?
AUDIENCE: I'm just a little confused
in the relationship between [INAUDIBLE]
SPEAKER 1: Yeah.
So the way to think--
AUDIENCE: I'm a little
confused about [INAUDIBLE]..
SPEAKER 1: Good question.
So the way to think about
it is, the hello component--
what I have here between
lines 13 and 22--
is a component that says "Hello".
And it's saying hello
to a particular person.
And the way that it's doing that is,
it's going to draw on its properties.
When I define the hello
component here, I don't yet
know what those properties are.
So I'm just saying, whatever those
properties are, plug in the name
here, even if I don't know the name yet.
I don't actually use the hello
component until inside of my app,
where inside of the app, I'm
saying, put a hello component here.
And in particular, put
a hello component here
who has a name property
equal to Josh, for example.
That's the way that that's working.
Yeah?
AUDIENCE: In the very
beginning of the first example
you used the line at
the bottom [INAUDIBLE]..
Why do you not need the same
format inside the [INAUDIBLE]??
SPEAKER 1: So why do I not
need a second ReactDOM.render
inside of the app class?
I only need the ReactDOM.render
function in order
to insert a component into the DOM.
So I want to insert into the DOM, at
this section of the page, the div that
has an id of app, I want to
insert the app component.
But the app component itself contains
the hello components already.
So I don't need to tell the
hello components where to go.
When I render the app
component, that will implicitly
render all of the components
that are within it.
Yeah?
AUDIENCE: You said the
alt values for [INAUDIBLE]
didn't provide a name [INAUDIBLE].
SPEAKER 1: If you didn't provide a name.
Sure, certainly.
So if I wanted to have
some sort of default--
if I have this.props.name and
there is no property called name,
then the value of this.props.name
is going to be a special value,
like undefined in JavaScript.
And so, a common way in JavaScript
to get at some sort of default is
by saying, this.props.name or--
two vertical bars meaning or--
and then in quotation marks, I can have
whatever I want the default name to be.
And so, maybe the default
name is going to be Andrew.
And now, even if I don't
include name on this last one,
just say hello, assuming
all goes right--
OK, it still says "Hello Andrew"
on the last iteration of the page.
And the reason that works is, when
I say this.props.name or Andrew,
if this.props.name has a value, then
this expression will short circuit,
so to speak.
It will just use this.props.name
because it already is a value.
But if this.props.name
is undefined, then
it's going to go to the thing on
the other side of the or expression
and say, OK, let's go
see the other thing.
And that, in that case, is Andrew--
in this case.
Question?
AUDIENCE: Can you have a
bunch of or expressions?
SPEAKER 1: Can you have a
bunch of or expressions?
Yes.
There shouldn't be any reason why not.
Other things?
OK.
So how do we feel
about this much so far?
Do we need more examples of this stuff?
Or do we want to move on?
AUDIENCE: Can we have another example?
SPEAKER 1: Sure.
So let's see another example.
In this case, let's try an example
that's also going to say hello.
Then we'll add an additional
feature to it in just a moment.
So we're going to have a
hello component that is just
going to say "Hello", for example.
And let's go ahead and just
return the hello component.
So all app is going to
do-- this component-- is
return a hello component.
And all that hello
component is going to do
is return an h1 that says
"Hello", for example.
So OK.
This is just going to say "Hello",
and that's all it's going to say.
Let me now add to this hello component.
Instead of just returning an h1, let me
wrap this whole thing inside of a div.
Let me also add a button
that says "Click Here".
So all right.
I have "Hello" and I have a
button that says "Click Here".
And I got that by just saying,
inside the hello component,
you should have an h1
one that says "Hello",
and you should also have a
button that says "Click Here."
Now once we have this button, we can
begin to add functionality and features
to this component.
So I could say, button
onClick equals something.
I can type in the name
of a function here
for what function should run
when this button is clicked on.
And so I could say, this.--
and I'll just call it "handleClick".
It's a pretty conventional
name for what should
happen when the button is clicked on.
Again, using curly braces to mean
plug in some JavaScript here.
And now I can say, OK, handleClick
is going to be a function,
using the arrow syntax for the function.
And this function right now is
just going to alert and say hi.
So let's try this.
We'll just refresh this page.
We have a "Hello" in h1, and a
button that says "Click Here".
When I click here, I get an alert.
And that alert says "Hi!"
Again, how did that work?
Inside of the hello component, we
have an h1 tag that just says "Hello",
and then a button.
And when we click on that button,
we're going to run this.handleClick.
In other words, the handleClick
function or method of this class--
this class called hello--
here is that handleClick function.
And all it's going to do is
display an alert that says "Hi!"
Questions about any of that so far?
All right, we'll slowly build up
into more sophisticated things.
Question, yeah?
AUDIENCE: So the same way the
name wasn't defined below here
but name is [INAUDIBLE] can we do
the same thing with [INAUDIBLE]
define that function differently
whenever we call hello with an app.
SPEAKER 1: Yes.
You can, in addition to just providing--
so before, we said, hello, name
equals Krishna, for example.
And we provided a string in as
the value of the property name.
You could, if you wanted
to, provide in a function,
like this.someFunction, and provide
some function into the components,
so that different components use
different functions to behave
in different ways.
That's something you can do as well.
We may see an example of that later.
Yeah?
AUDIENCE: Can you explain the line
at the bottom of the [INAUDIBLE]??
SPEAKER 1: The line at the-- this line?
Yep.
So this line is just taking this
component that we've written
and actually inserting
it into the application.
So as of this point,
all I've done is define,
this is what an app should look
like and how it should behave.
But I haven't actually taken that
app and put it into my web page.
It's not until line 40 here that I
actually say, take this app component
and actually insert it into whatever
the thing that has id app is,
and actually putting that
into the web application.
AUDIENCE: And you're not
using the [INAUDIBLE]??
SPEAKER 1: Yes.
In this case, app has a
hello component inside of it.
You could imagine that we probably don't
need it, because this app component is
just rendering the hello component.
So I could replace this with just hello.
But it doesn't matter in this case.
They're sort of interchangeable.
Yeah?
AUDIENCE: [INAUDIBLE] so
why is there [INAUDIBLE]??
SPEAKER 1: This is
referring to this component.
In other words, this hello component.
And the hello component currently
has two functions inside of it--
a render function or method,
and then handleClick.
And so we're saying, run the handleClick
method when the button is clicked on.
Yeah?
AUDIENCE: So how would you
pass an argument [INAUDIBLE]??
SPEAKER 1: How would you pass an--
AUDIENCE: If you wanted
to alert [INAUDIBLE]??
SPEAKER 1: Oh.
You can access this.props.whatever
from inside of your functions as well.
So if we still had a name
property, you could say, hi,
and then you could add on
this.props.name, for example.
You could access the properties
from inside of the functions.
Yeah?
AUDIENCE: So in the
beginning of the code
you wrote you had hello [INAUDIBLE]
and then in [INAUDIBLE]..
SPEAKER 1: Yep.
AUDIENCE: But how do you
know what this is referring
to because there is no [INAUDIBLE].
SPEAKER 1: So this is just
referring to the hello component.
And React is automatically
going to fill in props
with any of the properties that are
passed into the hello component.
So as long as you provide
attributes in this style of,
name of the component, and
then name equals something,
name is automatically going
to become one of the props.
And its value, in this
case, is going to be Julia.
Other things before we go on?
Yeah?
AUDIENCE: In a problem [INAUDIBLE].
SPEAKER 1: Yeah.
It could be any JavaScript value.
Yeah.
Yeah?
AUDIENCE: Does the handle click
function have to be defined like that
or could we define in the
normal function [INAUDIBLE]??
SPEAKER 1: You could
define it differently.
Although, the arrow function
syntax is going to--
it adds a couple little nuances.
It's going to make sure that it
handles the this binding correctly.
Long story short, JavaScript is
a little bit funky about the way
it handles the keyword "this" and
what the keyword "this" means.
And so to be safe, most of
the time for event handlers,
you'll want to define it this way.
No need to worry too
much about that though.
Yeah?
AUDIENCE: [INAUDIBLE] script
code separately [INAUDIBLE]..
SPEAKER 1: Yes.
In fact, in most production
environments, what you'll really do
is separate each component
into a different file--
into a different JavaScript
file, and then you'll
just combine them all together.
AUDIENCE: So it's only considered
JavaScript and not like [INAUDIBLE]??
It wouldn't be a different extension?
SPEAKER 1: Yeah.
So in actuality, what
most people will do--
and we'll probably take a look
at this tomorrow-- is that,
rather than have the page translate
all of the JSX into JavaScript
every single time, usually
what people will do
is they'll write the
JavaScript JSX code once.
And then before they actually
push their code to the internet,
they'll compile the code
into regular JavaScript,
and then deploy that, such
that it is playing JavaScript
that any browser can understand.
And that just works
for efficiency reasons,
so that you don't need to keep
recompiling the code every single time.
Because the recompiled code
is going to be the same.
But we'll take a look at that tomorrow.
All right.
So far, all we've done is come up
with a lot of JavaScript syntax
to do what would have been
pretty easy to do with just HTML.
So let's now actually
take a look at why it
is that React is going
to give us additional--
is going to make it easier to actually
write certain types of applications,
as opposed to just more wordy,
which seems to have been so far.
And the main reason that
it's going to be helpful
is when it comes to
thinking about state,
and the state of our application.
So far, when we've been
building applications,
we've been writing things imperatively.
When you were writing your
quiz application, for instance,
you changed the variable
referring to what question
number you're currently on in the quiz.
And then you had to actually say,
all right, let's update the page now.
Let's update the DOM to
actually use this new question.
Or when you changed the score
for the game, for instance,
you actually had to say, all
right, let's now update the page
to take this variable
relating to the score
and put it into the web application.
What we're going to do with React
with declarative programming is say,
on this page, we're going to
have this part of the page
just draw information
from whatever our data is.
So all we have to do in order
to update the page is just
change the data-- change the
state of the application.
And the view of the application--
what the application looks like--
is going to change to reflect that.
And so, let's do a
simple example of that.
We're going to define a class
that's going to count, much like we
did in a JavaScript
example before, whereby
we would have a counter that is going to
just count when you click a button that
says increment, increment, increment.
What we're going to do is, we're going
to define some application state.
And the initial state we need to define
when we first create the component.
And in Python, we did this via a
function called underscore, underscore
init--
the constructor function for
what happens when you first
create a new Python object.
JavaScript has something very similar.
It also has a constructor function.
It's actually called constructor.
And the constructor takes
as its arguments props--
all of the properties that the
component is going to have.
And there is one line here that has to
do with object oriented programming.
Because the counter
class-- this component--
is extending the
regular React component,
we need to add this special
line called super(props).
Again, don't worry too much about this.
But the long story short of this
line is, we're basically saying,
React's code for how a component
works needs to use those props.
And so we'll go ahead
and provide it to what's
called the super class,
which is React.component.
Again, no need to worry
too much about that line.
It just needs to be at the top of
your constructor every single time.
The interesting part
of the constructor is
that the constructor is
where we're going to define
the state of the application--
what it is that this component
needs to keep track of.
So this.state we're going to set
equal to some JavaScript object--
some collection of
key value pairs that's
going to represent the
state of the object,
or the state of this
particular component.
And so, the counter--
all it needs to do is keep
track of some variable that's
going to keep track of what
the current count value is.
So we can start by having
this.state have a key called
count and a value of 0.
Basically, just saying
that this component
is going to start off by
displaying a 0, for example.
So I'll show you that in
practice so that it hopefully
becomes a little bit clearer.
I'll go ahead and create a new file.
We'll call it counter.html.
And I'll go ahead and take all this
code, and put it back in here at least
for now.
And instead of rendering
a hello component,
I'm going to render a counter component.
And all right.
What is the counter
component going to do?
Well, inside of the constructor--
again, super(props), just to make
sure the constructor works OK--
we're going to define the
state of the application.
And the state of the application
is going to have a count of 0
to start with.
This is the starting value
of this particular piece
of the state of my counter.
And now, what is my render
function going to do?
Well the render function is going
to return a div inside of which
is going to just be this.state.count.
So in order to access the
state of my component,
I can say something
like, this.state.count,
and that's going to insert the current
state's count value into my application
at this point.
If I open up counter.html--
all right, great.
I see the number 0 because
that's the current value
of the state in JavaScript.
Questions about that so far?
Yeah?
AUDIENCE: Is props like--
[INAUDIBLE] or is it
specifically [INAUDIBLE]??
SPEAKER 1: Props is specific to--
it's a special name in React syntax.
AUDIENCE: Like [INAUDIBLE].
SPEAKER 1: Yeah, this is specific to
JavaScript, props is specific to React.
But they both are special names.
AUDIENCE: So then are props in general
more like keyword arguments in Python
as opposed to standard
arguments because it
would be like name equals something
as opposed to just putting in quotes
whatever the name you want.
SPEAKER 1: Yeah, you can think
of them as keyword arguments.
That's a good comparison.
Other things?
Yeah?
AUDIENCE: This is just like a
kind of general syntax question.
When should you use the semicolon?
SPEAKER 1: The semicolons are actually
usually optional in JavaScript.
So most of the time, it's not
going to matter whether you
include the semicolons or not.
I'll generally defer to using
the semicolons most of the time.
Though I will occasionally forget one.
Other things?
OK, so notice now that I can change
the value of the count variable
in the state object.
And that's going to change the page.
If I change count to 1, for
example, and refresh the page,
the page changes in
response to that state.
But of course, what
I'd really like to do
is to add some code such that this
component will modify its own state.
So let me go ahead and
take this.state.count,
put that inside of an h1 tag, and
add a button called "Increment".
And when I click the button--
onClick-- let's go ahead and run
the this.increment function, which
is a function that I'm going to write.
Here's my increment function.
And what I would like to do-- what you
think might be the easy thing to do is
just to say, this.state.count--
if I want to increment it, let's
just for simplicity's sake,
say change it to 1--
you might think I would say something
like this-- this.state.count equals 1.
And that would be nice to say.
But unfortunately, React is a little
bit more complicated than that.
React does not let you
modify the state directly.
And the reason for that is, React
is going to be smart about things.
It doesn't want to
reload parts of the page
if it doesn't need to,
for efficiency reasons.
And so, if you want to modify
the state of the application,
you need to use a special
function called this.setState.
This.setState is a function that's
going to take a JavaScript object,
and it's going to let me change
the state of the application.
So if I want to change it to
have a count of 1, for example,
this would be the code that I would use.
If I want to change the
state to have a count of 1,
I call this.setState, passing
in a JavaScript object,
setting count equal to 1.
I'll show you what that looks like,
and then we go back to the code.
Refresh the page, it's a 0.
And I have a button called "Increment".
And if I click the Increment
button, OK, the 0 changed to 1.
I didn't have to say, go into
the h1 tag and get rid of the 0
and replace it with a 1.
All I did was, initially, I said,
inside of the h1 tag, let's go ahead
and have whatever the value
of this.state.count is.
And if I ever change the state,
as via calling this.setState,
that's going to change the
value of this.state.count.
And that's going to result
in a different value being
inserted into the h1 tag there.
Question?
AUDIENCE: If your initial
state is [INAUDIBLE]
how does it update or would you
have reset the state for all
of the other variables?
SPEAKER 1: Oh, good question.
So the question is, what if my
state were more complicated?
In addition to having count, I
also have some other attribute
1 that's equal to "hi", and some
other attribute 2 the equal to "bye".
What happens to attribute
1 and attribute 2?
If I call setState, count goes to 1.
Any key that's not included
in the set.State object
is just going to remain unchanged.
So all setState is doing here is,
it's going to set count equal to 1.
But anything else in the state,
if I didn't mention it explicitly,
is just going to stay as is.
So you don't need to worry about
resetting those same values
to the same things again.
You just need to say, what is it
about the state that I want to change?
And put that into setState.
Yes?
AUDIENCE: In setState could you add
a new key to your state [INAUDIBLE]??
SPEAKER 1: In setState, could
you add a new key to your state?
You probably could, but
probably not a good idea to.
Any state you want, you probably
want to give it an initial value
inside of the setState.
Yes?
AUDIENCE: Is React an
abstraction of that [INAUDIBLE]??
You mentioned we're not writing the
JavaScript to go in [INAUDIBLE]..
So is React actually doing that
somewhere else or is it [INAUDIBLE]??
SPEAKER 1: Yes.
So React is taking care
of the process of actually
updating the DOM whenever it needs to.
But it's handling that logic.
And so, all we need to worry about
is what the page should look like.
And React does the heavy lifting
of figuring out what to insert
and what to remove from the DOM.
And the advantage here
is that it makes sure
that our data and our user
interface stay in sync--
that it's possible in
the quiz application,
if there were a bug in
your quiz application,
that you could have your variables not
be consistent with what it is the user
is seeing on the screen.
React is going to make sure
that those things always line Up
so it eliminates a large
class of potential bugs
that you could have in your application.
Yeah?
AUDIENCE: Why do we have
[INAUDIBLE] state instead or props?
SPEAKER 1: OK, what's the difference
between the state and props?
Props you can think of
as attributes that you're
going to provide into your component.
And the component never
changes its own props.
They're sort of information you
provide to the component about how
that component should behave.
And the component will
never change its own props.
State is something that a component
has that the component might
change at some point in the future.
So something like the name that we're
saying hello to, assuming we never
want the hello component to
change who is saying hello to,
that should be a prop.
But if it's something like the
counter, where the counter component is
going to change the
value of the count, that
should be part of the application state.
Yeah?
AUDIENCE: Can the initial
value of the state
be dependant on props
passing [INAUDIBLE]??
SPEAKER 1: Yes, you could make the
initial state dependent upon the props.
You can do that.
All right, so this application
doesn't quite work just yet.
Because right now it says 1, and I
click Increment, and it stays at 1.
Because all I'm doing right now on the
Increment is setting count equal to 1.
So of course, the simple way
to actually do the increment
would be to set count equal to what?
AUDIENCE: Count plus 1.
SPEAKER 1: Count plus 1.
And count is located
inside of this.state.
So I could say, this.state.count
plus 1, would be one way to do that.
So I set the count equal to whatever
the current count is plus 1.
I refresh the page.
OK, now it's 0.
I click Increment.
It increments to 1.
I click again, and every time, the
state of the application is changing
and the number is going
to increment as a result.
And so you can do that
as much as you want
to do by calling this.setState,
updating the state to be
whatever you want the new value to be.
Questions?
So, a small, little nuance--
for if you actually go on
to really want to start
building React applications
that are larger in scale--
in general, this is
considered poor design
to set the state and
reference this.state
inside of the setState function.
Reason being, if you have multiple
things happening simultaneously,
it's possible that two
this.setState calls
might be happening at a similar time.
And you might end up
with a race condition--
something similar to what we
described yesterday with SQL--
where someone else might modify the
value of this.state.count before we
have an opportunity to
actually run this function.
And so, in practice,
React recommends that,
if ever your new state is going
to depend on your previous state,
then you should actually
change this.setState.
So this.setState has a
couple of possibilities.
It can take just a
JavaScript object, describing
what the new state should be.
But it can also take as
its argument a function
from the old state to the new state.
So I could say, this.setState is
going to be a function that takes--
I'll call it "oldState" to be explicit--
a function from old state to--
and then, in parentheses--
the new state, where count is
going to be oldState.count plus 1.
Usually, this is just called
state and not oldState,
but I'm calling it oldState for clarity.
This is going to do basically the
same thing that our previous code did.
But it's a little bit more secure.
By providing a function
that says, here's
how you translate the old
state to the new state--
just take the old state
count and add 1 to it--
that avoids against the
possibility of race conditions.
So you'll see me do this from
time to time through the examples.
And just know that I'm doing
that for security purposes, just
to prevent against potential bugs.
But that's a small nuance
of the way it works.
Yeah?
AUDIENCE: Why is it necessary to--
or what is the differentiation
between referring to count as count
and then having refer to it as
the oldState or [INAUDIBLE]??
SPEAKER 1: So this count
on the left hand side
is just the key of a JavaScript object.
So it's-- much in the same way that
when I was defining state up here,
count was just the name of the key
of the object that I'm assigning
to a particular value.
Whereas, if I want to actually
reference the current value of count,
there is no variable
just called "count".
It's stored inside of this.state.
So to be able to access count,
I need to use this.state.count.
But if I just have
some JavaScript object,
I can have a key in that
object that is called "count".
That's the difference there.
Yeah?
AUDIENCE: Why is oldState [INAUDIBLE]?
SPEAKER 1: This is just a function.
And setState, React's logic is going
to take care of automatically saying,
if I provide a function
to setState, it's
going to pass the current
state into that function.
And then we're just going to
calculate the new state based on that.
AUDIENCE: Right, but why doesn't
oldState not count [INAUDIBLE]??
SPEAKER 1: React handles this part
of it for us by taking this function
and providing the current state to
it as the argument to that function.
So that when it's calculating what
it should set the new state to,
it's going to say, all right,
given this current state,
let me pass it to this function.
And whatever comes back
should be the updates
that I need to make to the new state.
I'll leave it up here if you
want to keep looking at it.
Yeah, another question?
AUDIENCE: So oldState
is also [INAUDIBLE]??
SPEAKER 1: Yeah.
In fact, normally it's
just called "state".
But for clarity, I
called it "oldState" so
that it would be a little bit clearer.
Yeah?
AUDIENCE: If you had a more
complex JavaScript object,
how would you index into
it given the dot index?
Like instead of [INAUDIBLE] you have
different elements within elements.
SPEAKER 1: You could
just chain dots together.
If you have some key that
is equal to some object,
and there's some key inside that,
you can continue to chain that.
Yeah?
AUDIENCE: Why does passing
the function of setState,
why does that prevent race conditions?
SPEAKER 1: So the reason
this is going to prevent
race conditions is because
React will make sure
that, when it's calling setState,
it's going to provide it
with the current value of the state.
And that's going to give it a new state.
And if there's some other setState
function happening elsewhere,
potentially concurrently,
it will make sure
that they don't interfere
with each other.
As opposed to, if we were just
referencing this.state.count,
if that line was taking
a long time, there
could potentially be interferences
there that are happening.
Yeah?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: Right.
This is something else on the same page
that could be happening concurrently.
This is a simple example.
So it's not really ever going to happen.
But you can imagine more complex
examples where that could be a problem.
OK, just for sake of example, let's
go ahead and try and extend this
to add a Decrement button to
decrease the value of the count.
So a button that says Decrement--
when I click it, onClick,
we'll do this.decrement.
And what Decrement is going
to be is a function that
sets the state of the application,
taking the old state and saying,
OK, the new count should be
whatever state.count was minus 1.
All right, I now have
an Increment button
that increases the value of the
count, and a Decrement button
that decreases the value of the count--
each working just by changing
the contents of this.state
by calling this.setState function.
Yes?
AUDIENCE: Can we instantiate
a multiple of these?
SPEAKER 1: Sure.
Can we instantiate a multiple of these?
If I add another counter here--
and why not?
I'll add a third counter--
we can reuse components
as much as we want.
And each component has its
own state inside of it.
So this component's count
state is going to be
entirely independent of this
component's count state.
And it's going to be entirely
independent of this one.
Questions?
Yeah?
AUDIENCE: Can you-- if you
wanted to pull in [INAUDIBLE]
how do you access it if you're
automatically generating because they
don't have their own IDs [INAUDIBLE].
If I wanted to use in
another function the value
of the [INAUDIBLE] JavaScript.
SPEAKER 1: Yeah, if you
wanted to use this value,
you would then just be able to
access the state of that component,
assuming you're inside
of that component.
And you can reference that state
to be able to do something with it.
And we'll see an example of that
in just a moment when we try
and build something a little bit larger.
All right, let's go ahead and
try a bit of a larger example.
Are there any other questions
about the basic ideas of what's
going on here so far?
Hopefully it'll become clearer
as we begin working with it too.
All right, what we're going
to do now is build a game.
And this is going to be a game that
I used to use with my younger brother
when he was growing up
starting to learn addition,
where we would just show him
addition questions like, 3 plus 5.
And you'd have to type in an answer.
And if you get the answer right,
you get some points for it.
We'll implement a graphical web-based
version of that sort of game.
And so I'll go ahead and create a
new file, and call it addition.html.
We'll start with the same
contents as hello, for now.
And all right, what is our
application going to do?
We don't need a hello component anymore.
We'll change the title of
hello to addition, for example.
And let's go ahead and
create this application.
We'll add a constructor.
And so, let me show you for a moment
what the final game should look like.
And then we can think
about, OK, what state
do we need to keep track of
in order to make this work?
And so let me go into--
All right, this is what this game
ultimately is going to look like.
It's going to show us
an addition problem.
You type in the answer.
You get it right, the score increases.
You get it wrong, and
the score stays the same.
So I get it right, and I
keep adding to my score.
And I get it wrong, and
the score doesn't change.
All right.
So given that-- that's the way we
want the application to behave--
what needs to be in the
state of this application?
What are the things I need
to keep track of here?
What changes about this application
is one way to think about this.
There are multiple things.
Yeah?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: The question
that's being shown.
Sure.
And the question that's
being shown has two parts.
It has num1, which is just
going to be some number.
We'll maybe start it with 1.
And it has num2, a second number
that's also-- we'll start it off
as 1, though these are going to change.
So great.
The numbers that are
shown on the screen--
this plus that-- those
are parts of the state,
because we might want to
change that part of the state.
What else is part of the
state of this application?
Yeah?
AUDIENCE: The score?
SPEAKER 1: The current score.
Great.
The score is part of the state.
And that's just going to be 0 for now.
Anything else you can think of?
Yeah?
AUDIENCE: The answer.
SPEAKER 1: Yeah, the answer.
The thing that I'm currently typing
in the input field-- in the response
field.
That's also going to be
part of the state as well.
So I'll go ahead and
add response, and just
set that equal to the empty string.
Because initially, I haven't
typed in anything at all.
So great.
Here are some basic components
that are going to make up
the state of this application.
And let's go ahead and
render this application.
We're going to render a div.
And maybe in an h1, just for now, we'll
go ahead and have the addition problem
here.
this.state.num1 plus this.state.num2.
That's going to be the question
that I'm ultimately going to ask.
It's just this plus that.
If I open up addition.html--
all right, great.
I see an addition problem where I'm
drawing the numbers from the state.
later if I change the state
and change those numbers,
this page will change automatically.
And now in addition to that, I'm
also going to need an input field--
an input field whose value is
going to be this.state.response,
in other words, whatever the
user has currently typed in.
Questions about that?
All right, so now I have a place
where I can ask a question,
and a place where I can type an answer.
And now, if I actually try and type
an answer, something sort of strange
happens.
But it will make sense if you think
about what's actually happening
in my code and what I've written.
If I try and press 2, for
example, to answer 2--
I press 2, but OK, nothing
showed up in the text field.
I can keep pressing whatever
keys I want to on the keyboard,
and nothing's showing
up in the text field.
It's highlighted, my cursor is there.
So why is nothing changing
in the text field?
Any thoughts?
Yeah?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: Yeah, exactly.
Response inside of my state
is set to the empty string.
And this input field right
now, I'm saying its value
is this.state.response.
And this.state.response
is never changing.
And so what's in the input field
is always going to be empty.
It's never going to have
anything else there.
So what I need to do is
actually add some code to say,
what should happen when I actually
change the value of the input field?
So the input field has a
property called "onChange".
And I'm going to say, when you change
the input field, let's call a function.
And I'm just going to
call it "updateResponse".
So this.updateResponse is
going to be a function that's
going to handle when I type
something into the input field.
OK, so here is updateResponse.
It's going to be a function.
That function-- all functions
that are event handlers
can take as argument their event.
And we're going to need this in
just a moment, and you''ll see why.
Because what I want to do is,
I want to update the state--
this.setState-- and I want to set
the response to event.target.value.
And event.target.value is
nothing specific to React.
It's just JavaScript for
saying, here's the event--
the event of changing the input field.
The event's target is what triggered the
event-- the input field, in particular.
And what is the current value
of the input field, meaning,
what it is that I've typed
into the input field.
I'm going to update the
response to be that.
So what have I done here?
I've said on this input
field, whenever it changes,
call the updateResponse function.
And the updateResponse function is going
to set the state of my application,
updating the current
value of a response.
And so, if I press Refresh now, now
I can actually type numbers in here.
I can add 2, 3, whatever number I want.
If I scroll back here, you can
actually see what I'm doing here.
If I say, current guess is, and then
let me fill in this.state.response--
just plug in whatever
this.state.response is right now.
If I refresh the page,
and I start typing 2--
current guess is 2.
8, current guess is 28.
2, current guess is 2.
Empty, the [INAUDIBLE] goes empty.
The page is changing in
response to the state
without me needing to go in
and actually modify things,
because I have pulling from this.state
inside of the render function.
Yeah?
AUDIENCE: Does the order of the
functions matter in the same way?
Is it fine to have updateResponse
after Render or is it fine to
have it before as well?
SPEAKER 1: The order of the
functions doesn't really
matter-- updateResponse could be
higher up, if I wanted it to be.
AUDIENCE: [INAUDIBLE]
SPEAKER 1: Yeah, when
you define the class,
it's going to go
through all the methods.
So it knows what methods it has.
And so it doesn't really
matter what order they're in.
Yep?
AUDIENCE: How does the updateResponse
know that event is [INAUDIBLE]??
SPEAKER 1: I specify it here, that
the input's onChange attribute
is this.updateResponse.
So when the input field
changes, it's going
to call the updateResponse function.
And the event that did that calling
is the input field's change event.
And so it has access to the
input field and can access
the current value of the input field.
Other things so far?
All right, let me also, instead
of showing the current score,
let me go ahead and have
a div where I'm going to--
let me actually show the current score.
I'll say Score: this.state.score to
say, all right, let's plug in the score
into this section of the page.
So now, OK, 1 plus 1-- a place to
input the answer, and a score that's
currently 0,
What I'd like to do now is, when I
type in a number and press Return,
for example, that's going
to trigger submitting
my response as a potential answer.
And so, the input field--
there is no attribute of the input field
that's like, when you press Return.
But there is onKeyPress--
like, press any key.
And so we're going to need to use that.
We're going to need to say, whenever
a key is pressed, let's go ahead
and call a function.
We'll call it this.inputKeyPress.
But again, it could be
called anything we want to.
And lets, inside of the inputKeyPress
function, we'll take the event.
If I want to get what the key
is that's actually pressed,
that's as simple as saying, event.key.
And so, if event.key is equal to enter,
and JavaScript is a slight difference
between what double equal sign is
and what triple equal sign is--
triple equal sign is going
to do strict equality,
making sure things really match
including the types of things.
And so, in general, it's safest to
use triple equal side, if you can.
So I'm saying, if the key
that I press is Enter,
then I want to go
ahead and do something.
And so, one thing I could do is--
well, let me pose the question.
What do I want to do now?
Now that I've pressed
Enter, and now I'm running
code that will run when I press Enter
after typing in a potential number.
What should happen?
Check what?
AUDIENCE: Check if the answer is right.
SPEAKER 1: Check if the answer is right.
Great.
So I want to check if
the answer is right.
And so, what is the answer?
What is the answer?
Well the answer is stored
inside of this.state.response.
That is what it is that
the user has typed in.
But of course, what the user
is typed in is a string.
And so in order to turn it
into an integer, in Python,
we just used a function called int.
In JavaScript, that happens
to be called parseInt--
to say, take the string,
parse it as an integer,
and save it inside of this
variable called response.
And so now, what is the code for
checking if I got the answer right?
What does that look like?
How do I know I got this
addition problem right?
Yeah?
AUDIENCE: If answer equals [INAUDIBLE].
SPEAKER 1: Great.
I've gotten num1 and num2 here
stored inside of the state.
So to check if I got the answer
correct, I'm going to say,
if answer is equal to
this.state.num1 plus this.state.num2.
I'm going to do something
if the answer is right,
else I need to do something
if the answer is wrong.
Questions about this much?
I've now verified whether the answer
is right or wrong based on the state.
Yeah?
AUDIENCE: Does the program know
that the values are numeric?
SPEAKER 1: Does the program know
that the values are numeric?
No, it's possible that parseInt is going
to get something that's not numeric.
And that's why we have to try and
parse it first into an integer.
num1 and num2 are definitely
going to be integer numbers.
Because we've said in this.state
that they are, in fact, integers.
But the response, you're
right, is a string.
All right.
So if the answer is right,
we want to change the state.
And how would we want
to change the state?
I'll go ahead and say state
arrow, so that we can base it
off the previous state if we need to.
But what about the state needs to
change if I got the answer correct?
Just in English, not
necessarily in code.
Yeah?
AUDIENCE: The score [INAUDIBLE].
SPEAKER 1: The score.
Great.
So the score needs to change.
The score needs to become
state.score plus one.
And the numbers need to change too.
I want to change what
number one or number two
are so I can show a different question.
So num1 is going to be a new number.
And let me just go ahead
and pick a random number.
And so, a common way that you'll
see of generating random numbers--
most languages have a way of generating
a random number between 0 and 1.
And in Python, the way to
generate a random number--
or in JavaScript, to do
that it's math.random.
That's going to generate a
random number between 0 and 1.
If I multiply that by 10,
that's going to generate
for me a random number between 0 and
10, non-inclusive on the upper bound
at least.
And so, if I want to generate-- take
a potential floating point number,
like 2.8--
a decimal number between 0 and 10--
and convert it into an integer,
I'll either need to take the floor
of that or the ceiling of that.
I'll go ahead and take
the ceiling of that
in order to, say, if it was
p make it 3, for example.
And so what I get by doing this is I
get a random number between 1 and 10.
By taking a random number,
multiplying it by 10,
and taking the ceiling of that--
that's a math trick
you'll often see, where
you can generate a random
number between 0 and 1,
and turn it into a random number
in any range that you want to.
So this code is basically
just saying, let num1
be some random number between 1 and 10.
And I'll go ahead and do
the same thing for num2.
num2 is also just going
to be some random number
in the range from 1 to 10.
Is there anything else about
the state that needs to change?
Yeah?
AUDIENCE: You need to
clear the response.
SPEAKER 1: Yeah, I need
to clear the response.
And let's see what happens
if I don't do that.
And then we'll actually
go back and do it.
I'll go ahead and open up addition.html.
Here's the problem-- 1 plus 1.
I get the correct answer.
I'll type in 2, and press Return.
The problem changed.
My score increased.
But the two inside the
input field are still there.
I'd ideally like to just clear it out
when you get the question correct,
so that I can try typing
in something else.
So in addition to updating
the score, num1 and num2,
I'm also going to say a response
is equal to the empty string--
clear out the response so that I can
type something new in in this position.
So I'll refresh this page--
1 plus 1-- I type in a number, 2.
I get the question correct.
The score increases.
I get a new question.
I answer the question correctly, I get
a new question and the score increases.
What should happen if I
get a question wrong--
answer incorrectly?
Right now, nothing's happening.
What should happen?
What about the state needs to change?
Yeah?
AUDIENCE: The [INAUDIBLE] the
score did not change [INAUDIBLE]..
SPEAKER 1: Sure.
Let's at least clear out the response,
so that we can say, you know what?
If you get the question wrong,
let's clear out the response
so that you can try again.
So now, if I have a question
and I happen to get it wrong,
I type the incorrect answer.
The problems don't change.
The score doesn't change.
But at least the input
field is now cleared out so
that I can actually type
in something new again.
Questions about what
we've done here so far?
Hopefully now you're starting
to see the power that React
is going to give you in
building user interfaces--
that we're able to update
the score, that we're
able to have the problems change
all without me having to say,
go into the DOM and actually
change what's at these values--
no query selectors to
try and grab things.
I just changed the state
of the application,
the parts of the component
that are going to change,
and the web page is going to
update on its own via React
in order to reflect what it is
that I want the page to look like.
Yeah?
AUDIENCE: If you want to save
the state in a simple database
or save it so it's constant for
the next user, is there an easy way
to do that with React?
SPEAKER 1: So if you wanted to
save the state somewhere-- it
depends on where you want to save it.
So, if you want to save
it on the client side
so that the next time
you open up the page
it's still there, that you
can use local storage for.
And we'll probably take a look
at an example of that tomorrow.
If you want to save it on
the server, then you're
going to need to send the data
off to the server somehow.
And you can do that using
an Ajax request like we
were talking about a couple
of days ago, just to say,
send this data off to the server
so that you can store it somewhere.
But yeah, you could do that.
Other things?
Yeah?
AUDIENCE: What happens now if you
enter something other than a number?
SPEAKER 1: If I enter
something other than a number--
So.
I type in "hi", for
example, and press Return--
it's going to count that is incorrect.
Why does it count that is incorrect?
It's because, if I take parseInt
and pass in a string like "hi",
what I get is a special JavaScript
value called NAN, or not a number.
And NAN-- what I'm
really going to be doing
is comparing whether that value is
equal to, like, 1 plus 1, for example.
And that's always going to be false.
Because not a number is not
going to be equal to any number.
And so, the if condition
and the logic here
is going to handle dealing
with non-numeric inputs for me.
Because answer is just never
going to be equal to that sum
if answer is not a number.
But yeah.
Good question.
And good corner case to consider.
Yeah?
Oh I-- so yeah, if you
look at the example online,
I add the square to num1 and num2.
That's to, if you wanted to
update the game a little bit
to make it a little more difficult,
such that every time you get a question
right the numbers get bigger--
if you take the score and
add it to the numbers,
then you'll end up getting
more difficult math questions
as the score gets higher.
But yeah, no need to do that.
Yep?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: If you put in a single--
AUDIENCE: Character in response.
SPEAKER 1: Oh, just the letter A?
AUDIENCE: Yeah.
SPEAKER 1: No, that's still
not going to be a number.
Because-- yeah, it's going to
try and take the literal string
and treat it like a number.
And the character A, even though
it has an Ascii value that
is a numeric value, the
character itself is not
what we would generally
consider to be a number.
Other questions?
All right, so let's try and do
something a little bit different.
Let's try and now say, when
you reach a certain score,
I would like to display
some different methods.
Like, when I get to a score
of 5, for example, let's
say, OK, you won the game.
So how might I go about doing that?
Well I don't actually need to
add anything else to the state.
All I need to do here is to say--
all right, this render function--
instead of having it
render the entire game,
let me just rename this
function to renderProblem
for rendering a particular
problem that I want to answer.
And let me go ahead and add
another function called renderWin,
for example, that returns a div that--
we'll return it to h1.
"Congratulations, you win!"
So now I have two different functions--
renderProblem and renderWin.
And now in my actual render
function, I can add logic to this.
Render doesn't just need
to return something--
I can add any JavaScript logic I want.
I can say, if this.state.score
is at least 5,
then go ahead and return renderWin.
Otherwise, if the score is not at
least 5, let me return renderProblem.
So I've added some logic
to the render function
known as conditional rendering.
Depending upon the value of the
state, I can render different things
on the page.
And so what's that going to do?
By adding this simple logic, now--
Uh-oh, something's wrong.
"renderProblem is not defined".
Oh.
this.renderWin and
this.renderProblem-- because they're
both methods inside of this component.
Refresh the page.
We get 1 plus 1.
And so the question correctly.
Answer the question correctly.
Correct, correct.
And when I get the 5th
question correct, now suddenly
my score is going to be at least 5.
And the interface changes.
Nothing congratulations
you win because we've
reached a different branching
point in this conditional.
You get the question
correct, and as a result,
we get a different output that
gets displayed to the screen.
Yeah?
AUDIENCE: If you reload the page
is that going to [INAUDIBLE]??
SPEAKER 1: As soon as you reload
the page, in this instance,
we get reset back to the original state.
Because we're reloading the whole page,
it's running the JavaScript again.
It's going to reconstruct
all of my components,
and it's going to reset the state back
to the original value of the state.
And so, as someone
was mentioning before,
you could save the
state in local storage--
and we'll probably see an
example of that tomorrow--
if you wanted to retrieve
it back later afterwards.
Yeah?
AUDIENCE: Is there a reason
you always start with 1 plus 1
or could you start with a random number?
SPEAKER 1: If you wanted to, you
could start with random numbers
other than 1 plus 1.
You'd just have to change the
initial value of the state,
changing them to random numbers instead
of having them initially be 1 and 1.
But yeah, you could do that too.
Yep?
AUDIENCE: So is it calling render
whenever you change the state
or when it is calling render, how does
it know to call render [INAUDIBLE]??
SPEAKER 1: So when React
calls render is part
of React's abstraction,
whereby it's going
to call render whenever it needs to.
And React is going to compute based upon
the state when it needs to re-render.
And in particular, it's not even
going to re-render everything.
It's only going to re-render the
parts of the render's return value
that actually need to change.
And so, if I'm typing
something into the input field,
the contents of the h1 that's
displaying the problem-- something
plus something-- that's not changing.
And so React is not going
to bother re rendering
that part, even though other parts
of the application are changing.
And so React is going to be
smart about it-- figuring out
which parts of the DOM need to be
reloaded and re rendered in response
to the changing state
of the application.
Other things?
Yeah?
AUDIENCE: [INAUDIBLE] file?
SPEAKER 1: Yes, you could definitely
separate stuff into different files.
And in fact, tomorrow
we'll probably take a look
at the more canonical
way of doing things
like this, whereby we'll
actually use a little bit of node
in order to do that too.
But more on that later.
Yeah?
AUDIENCE: You had the question
go red when it was wrong.
Is that a set property of
the state or [INAUDIBLE]??
SPEAKER 1: Oh, good question.
So in the application that
I demonstrated a moment ago,
the original version--
when the question was wrong, I
changed the color of the problem.
Like we changed it from just
being black to being red text.
And so we could implement
that feature here now.
In order to do that, whether
or not the text is read,
that's an additional piece of the state.
That's something that the application
state needs to know about.
And so I'll go ahead and
add to this dot state
a key called "Incorrect" that
is going to be equal to false.
I saw a couple of red frowny faces.
Questions before I go on?
All right, feel free to
find me during project time
or ask questions later
too, if you want to.
All right, so initially, we're
going to say Incorrect is false,
meaning the problem is not incorrect.
And let me go ahead and say, here,
if you get the question wrong,
let me set Incorrect
to true, for example.
We'll change incorrect from false
to true if we get it incorrect.
And now, what I'm going
to do is take this h1--
the information that's
displaying the problem--
and I'm going to give it a class name.
A class name is basically the same thing
as what a class is in regular HTML.
But in React, we have to call
it class name instead of class,
because class is already a keyword
in React, or in JavaScript more
generally, that stands in for
the class of the application.
And so I'm going to give
this h1 a class name.
And in order to do this, I'm going
to use some special JavaScript
syntax called the ternary operator.
The ternary operator is very common.
You'll see it in react a lot.
But basically, the idea
of the ternary operator
is I say, I ask a Boolean
expression question.
I add a question mark.
And then, I have a value for
if the expression is true,
and then a value for if
the expression is false.
And so, this is like a shorthand way
of creating and if/else expression.
I basically just put a Boolean
expression on the first hand side,
add a question mark, and
then add two values--
a value if the expression
evaluates to true,
and a value for if it
evaluates to false.
And so I can say class name--
all right, if this.state.incorrect--
meaning, if inside the state
I've gotten the question wrong,
let me go ahead and give the
h1 a class name of incorrect.
But otherwise if I didn't
get it incorrect then,
it doesn't need a class name.
So I'll just go ahead and put two
double quotes, meaning empty string--
no class name here.
And so now, only if the
problem is incorrect,
then h1 is going to have
a class of incorrect.
And so now, up in this header,
I can just do normal CSS code.
I can add some style code that says,
if something has a class of incorrect,
then go ahead and color it red.
And so now, by adding
style for what should
happen if you have a class of
incorrect, and by adding to this h1
a class name that is only going
to be incorrect if I've actually
gotten the question wrong.
Now when I load this page, I type
in the answer, I get it right.
I type an answer and I get it
wrong, the color changes to red.
Because it's gotten that
new class of incorrect.
There is a small bug here.
Anyone catch what the bug might be
based on the code that I've written?
Yeah?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: Will it switch back?
Will it?
I type 15, I get the answer correct.
And no, I get a new problem.
But the colored didn't switch back.
And that's because I
need to additionally
say, down here, if I
get the question right,
well then, I better set
incorrect equal to false
so that it goes back to having
a color pf black afterwards.
So I'll try again.
I get the question right.
I get the question wrong,
and I get the question right,
it changes back from red to black.
By changing the value of the state,
the interface updates automatically.
What questions you have?
All right.
In that case, what I
thought we'd do is, I'll
help get you started on what's
going to be the morning project.
And one of the canonical things to do
with React when you first try to do it
is to try and create a
to-do list application--
an application where you can just
add tasks and remove tasks from them.
And so we'll go ahead
and give that a try.
In order to do that, there are a couple
of useful JavaScript tips and tricks
that you might want
to take advantage of.
So recall that when you
have application state,
you should never change state directly.
You should never say,
this.state.whatever,
something equals something else in
order to change the state directly.
You should always be
calling this.setState.
But if you wanted to
manipulate the state
without changing the original state, you
might want to create a copy of a list.
And so, this is something that's
probably going to come up.
So I'll show it to you now.
If I have a list of things,
like list1 equals 1, 2, 3, 4, 5,
and I want to make a copy of that list
so that I can manipulate that copy,
you can do something like this.
The dot dot dot list1 is basically
saying, fill in list1 into this list.
And so, copy is also going
to be a list, 1, 2, 3, 4, 5.
But it's going to be
a copy of that list.
And we'll see in a moment
why that might be helpful.
If I wanted to make a copy of the list
and add something to the end of it,
well then it's as simple
as syntax like this.
list1 is 1, 2, 3, 4, 5.
list2 is fill in all of list1
here, and then add the number 6.
And you can imagine this might be
useful if, for instance, you're
building a to-do list application.
You have a list of things to do, and
you want to add on one more thing
to do at the end, for example.
You've got a whole list, and you want
to tack on something at the end of it.
So that might be useful as well.
You might also want to
delete something from a list.
And in order to remove
something from a list,
one easy way to do that in
JavaScript is the splice method.
And so, if I have list1--
1, 2, 3, 4, 5--
and I say, list1.splice, and then
3 comma 1, what that's saying is,
pull out elements starting at index 3.
That's the first argument.
And the second argument is how many
things should I pull out of that list.
And so here I'm saying, from index
3 in the array, which is the number
4, go ahead and remove one element.
And so now we get 1 2, 3, 5.
So just a couple of little tips and
tricks for interacting with JavaScript
lists, since it's a syntax you
probably haven't seen before,
but that's ultimately
going to be helpful.
So let's go ahead and get started
with this to-do list application.
I'll go ahead and create a new file.
We'll call it todo.html.
I'll go ahead and copy the contents
of hello just to get us started.
The title will be todo.
And we'll delete the hello component.
We don't really need it.
And OK, here's our application.
Constructor, props.
What is the state of our
to-do list application?
What are the things we
need to keep track of?
Yeah?
AUDIENCE: [INAUDIBLE] do you use
setState and append to a list?
Like if you had this [INAUDIBLE]?
SPEAKER 1: If you wanted to
append something to a list
by setting the state, you
should do it this way--
by making a copy of the original
list, and then adding something
to the end of it.
And that's, again,
for security reasons--
for the race condition issue
that I mentioned before--
that you want to make
a copy of the state
instead of actually
modifying the state directly.
OK, a to-do list application--
what do I need to keep track of?
And I'll show you what the
finished product should look like,
in case that helps.
We'll just create something looks
a little something like this.
We've got tasks, a window bar that
shows you how many tasks do you have.
You add a thing to do,
add that as another task.
Pet otter, add that as another task.
So we've got this growing list of tasks.
And if you want to,
you can add the support
for deleting them, checking them off.
So what is the state of the application?
What things can change?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: The tasks.
Yeah, all the tasks themselves.
That's going to start out
just being an empty array.
There are no tasks to begin with.
And what else?
There's one other piece of the state.
What else changes here?
Yeah?
AUDIENCE: Whether
they're complete or not.
SPEAKER 1: Whether
they're complete or not.
Sure.
You could implement it by keeping track
of whether the task is complete or not.
You could also implement it just
by removing the task from the list
if it's complete, since
it's not going to come back.
So certainly, that's something
you could add if you wanted to.
AUDIENCE: Input.
SPEAKER 1: The input field.
Great.
This is something that changes.
When I start typing, the value
of the input field changes.
And so I'll go ahead and give
it an input that, at least
initially, is going to be blank.
What is the render function going to do?
Well, let's go ahead and render an
h1 that just says Tasks, for example,
and an unordered list where I'm
just going to list all of the tasks.
And so how am I going to do that?
Let me just go ahead
and, for sake of example,
start us off with a couple of
tasks, like thing1, thing2, thing3,
in terms of things to do.
If I want to create one list item for
every single thing in this.state.tasks,
well then we can go back
to functional programming,
which we introduced a couple of
days ago, and recall that if I--
what I want to insert here is
going to be this.state.tasks,
and then I can say, .map
Remember, map is a function
that takes an array,
and goes over every
element in the array,
and lets me apply some function to it.
And so I'm going to map over here.
And we're going to map over and take
every task, and we're going to--
I'll go ahead and fix
the spacing a little bit.
And for every task, we're going to
go ahead and return some list item.
And that list item, at least for now,
we'll just go ahead and say, let's
print out the task there.
So long story short, we
have an unordered list.
And we're going to take
inside this unordered list,
go over this.state.tasks, mapping
over it, going one task at a time.
And for each task, we're going
to go ahead and print out
a list item that's going to be equal
to whatever the value of the task is.
Let me go ahead and
open up todo.html now,
so we can see what that looks like.
All right, great.
Now we have tasks, and we have
this loop that's going over,
creating one list item for each element.
Yeah?
AUDIENCE: Could you do a for loop?
SPEAKER 1: You could also do a for
loop in order to do this same thing.
So you'd do a for loop to sort of add
to this growing string, for instance,
and then insert that
string into the HTML page.
You could do that too.
One error you'll notice here-- and this
is just a nuance of React that might be
worth solving--
is, you get a warning
if you do something
like this, which is that each
child in an array or iterator
should have a unique key prop.
And basically, all this is saying is
that, if you are looping over something
and creating a whole
bunch of elements, React
would like you to give all of
them a unique property called key.
And it does this for efficiency sake.
So that if you're updating
only one element in the list,
it doesn't need to also
update all the other elements.
It can just update the one in question.
And so, we'll give this a unique key.
The task name might not
necessarily be unique.
But an additional feature of map is
that it can loop over all the tasks.
But you can also give this function
the optional argument, i for index,
that will let you access which index
into the array is this right now.
And so, I'll go ahead
and give this a key
of i, meaning the first one will be
task 0, then 1, then 2, so forth.
Yes?
AUDIENCE: [INAUDIBLE]
SPEAKER 1: So if you start splicing the
array, the indices will be the same.
But React is going to be
smart enough to know that,
because the element at that index
has changed, that it's still going
to be able to re-render it correctly.
OK, so if you do that, just
add key equals i to it.
Then when you refresh it,
you'll get rid of that warning.
So all right, great.
We've gotten this list of tasks now.
We're also going to want an input
field underneath this list of tasks,
whereby I can have an input field
that is going to have a value
of this.state.input, and
probably also a button--
and I'll actually put all
this inside of a div--
and a button called Add Task
So I have an input field whose value is
whatever the current value of the input
is, and also a button that's
going to add a new task for me.
I refresh this page.
And all right, now I
have an input field,
and I have a button to add tasks.
But much like with the
addition game example,
if I start trying to type a task
here, nothing shows up on the screen.
Because I actually need to
add, in the same as before,
an onChange handler to say, when I
change the value of the input field,
call the handle change function.
And OK, what does handle
change going to do?
Well, it's going to be a function that
just sets the state the function needs
to take the event as its argument.
And we're going to set the state.
And the new value of the input
is the event.target.value.
Same as before-- when I make
a change to the input field,
update the input value
inside of my state currently.
So I refresh this,
and now I can actually
type a new task into the task page.
Clicking Add Task, of course,
doesn't really do anything just yet.
So let's make it do something.
Button onClick-- let's go ahead and
run a function called this.addTask,
for example, for when
you click on a button.
addTask is going to go
ahead and be a function.
And we're probably going to want
to update the state somehow here.
Set the state to be something new.
I'll go ahead and do this.setState.
It's going to take the
original state as its input.
And the new state is going to be what?
What should the new tasks be?
Yeah?
AUDIENCE: [INAUDIBLE] input.
SPEAKER 1: Great.
It's going to be whatever the
current list is-- state.tasks--
and then state.input, which is
whatever it is that I've currently
typed into the text field.
So I'm updating the
state, adding that task.
I'll go ahead and remove
these sample tasks so
that we can get started with something.
Go ahead and refresh the page.
So tasks-- I can type
task1 here, add the task,
and all right, task1 shows up.
Granted, it stayed
here in the text field,
but that's something
we can fix later too.
I type in a second task,
click Add Task, and all right.
That task is added to the list as well.
Questions about what
we've done here so far?
All right.
In that case, I'll post a
distribution code in just a moment.
But we'll go ahead and break
for our morning project.
Here we'll create the to-do list app.
We're going to allow the
user to type in a task,
add a new task to a list
of tasks, and delete tasks
by clicking a button next to each task.
I'll give you a suggestion of
the order in which to do things.
I'll post a distribution
code in a moment,
if you'd like to take a look at it
and use that as a reference point.
I'd start by just displaying on
screen the current number of tasks.
See if you can figure out a
way to, on the application,
get the page to draw information
from the state to display, like,
you currently have four tasks
in your task list, for example,
and display that information.
Once you get that
working, go ahead and see
if you can clear out the input
field after we add a new task.
So you type something
in, you press add task,
and the input field clears out so
that you can type in a new task.
The thing to do after
that is going to be,
let's take each task in the task list.
In addition to just
displaying the task, also
display a button next to it with
maybe an X or a checkmark to say,
completing this task.
And just add that button there so that
every list item has a button with it.
And then finally, as a final
challenge, if you're up for it,
make it such that when
you click on that button,
that actually triggers changing
the state so that we remove
that task from the list
of tasks, therefore
allowing you to complete and add
new tasks to your task application.
If you'd like to, feel free
to add other features as well.
Or feel free to take the game
from earlier this morning
and add features to that too
as part of the morning project.
We'll go ahead and all just stay
in this room for this morning.
And we'll go until 12:30, and then break
for lunch then, and reconvene at 2:00.
