All right we're getting closer and closer to having our app look like this but we clearly see that we
have a search box here.
So in this video we're going to work on having this interactive. Looking back at our app,
we see that
well we definitely need a title and the search box, so let's create that.
If I go to index.js
I think now that we're officially building an app, instead of having the "Cardlist" component here we should
have one big component called "App", and this "App" will be the father of all our children, all our components
Let's do that. Let's build the "App" component first
And this "App" component again will "import React from 'react';"
and "App" will equal
the "CardList" component which we can just copy and put in here
And again, changing this to "Babel", we want to import
the "CardList" component
and we also want to have our "robots" actually imported in here
so we have access to it
And then finally we now just want to render the app component so we can just bring this back the way
it was
We save. We need to obviously export our app
So we'll say "export default App;", save this
Let's go back
Yep
Everything is still working
Now within the "CardList" we also have a header
So we'll do "h1", that'll say "RoboFriends"
and again remember that we need to return just one single parent
ao we need to do something like a "div" to wrap it
and I need to close this "h1" tag
All right
I have my "robot friends" title and we also need a search box. And although "h1" was easy and we now have to
build a component for it,
It sounds like we probably want to create a search box component for this app, so let's do that
I'm going to say "import SearchBox" from a file that we'll create called "SearchBox". We will create a new
file
and this file will have "import React from 'react';"
and the search box
will have a function that returns -
Let's think about what it returns
Well it definitely returns an input, right?
That is type of 'search'
And let's also have a placeholder -
let's close this - and placeholder that says 'search robots'
We close this and save and we have to export: "export default SearchBox;", save, "Compiled successfully!"
All right! We have our search box
But, well, it's not searching anything right now
Let's add this on a new line, just so it looks nicer. And it's always a good idea, just in case you want
to add more things to the search box, to wrap everything in a "div"
So I'm going to do that right now.
And this "div" will just have a "className" of "padding2"
again using [tag-ons], and with the "input" we can do a "className"
and I just know these look good
so I'm just going to copy and paste here
just padding
with background "lightest-blue"
If I do this, and - let's go back
All right
This looks better -
We want to center everything
So maybe in the app we can just add a "className"
equals to "text center"
see if that works
There you go
That's much better
I like this already
Now, how can we make this interactive?
Up until now we've just had these static web sites but real web sites are interactive, right?
Well let's think about this logically
We have an app
We have a "SearchBox"
And we have a "CardList", but the search box component needs to communicate with the card list, and same
with the card list. "CardList"
needs to know what is in the search box so that it can filter out robots accordingly
Let's go back to our image that we have of one way data flow. Looking at this
we have the app component, and then the card list component that has cards, and then the search box component
that, well, doesn't have any children now
But in order for these two to communicate we have a one way data flow, that is they need to send their
information to their parent and the parent tells them what to do
Now how can we do that
Up until now we just had some data that we just trickled down, but we never had it where one of the children
had to modify data or communicate with a neighbor.
Well, in order to do this
React has an idea of something called "state". Up until now we learned about props such as properties
that we keep passing down
but we've never changed them because React just reads the props.
If I go to "CardList" it just reads the props that it receives and it just renders something. And this one-
way data flow is really nice because this "CardList" is a pure function. It receives an input and then
it always returns the same output
So if robots are always the same it's always going to return the same thing
It's deterministic, pure functions, and it's something that we've talked about before. And this is a really
really good thing.
These components are what's called "pure components", and some even call it "dumb components"
It just means that they don't really need to know about anything other than the fact that they're pure
functions that receive something and return something.
And this is really nice because we always know what this is going to look like, and that's all we had
up until this point
But now we have to worry about something other than props
Props never change. Props are always just inputs that we get
and we've never modified them
But in this case we need a memory in our app
We need this to communicate with this, and also change and update accordingly
And that's what "state" is in React. "State" - and you'll hear this in computer programming a lot - simply means
the description of your app. A "state" is simply an object - an object that describes your application
And this "state" which describes our application is the robots, and whatever's entered in the search box
and "state" is able to change
We're able to change the value of the search box, the value of the input, and we're able to change what
robot's array means
What gets displayed
This is a rule that you just have to remember
Props are simply things that come out of "state"
So a parent feeds "state" into a child component and as soon as a child (components) component receives a
"state" it's a property. That child can never change that property. The parent just tells it what the "state"
is and the child receives it as "robots"
So the first thing we need to do is to start being able to use "state" in our app, the description of what
our "state" should be
So let's just do a constant "state" for now and show you that our "state" needs to have a "robots" array
and it needs to have, let's call it "searchfield"
And this is just whatever our search field needs
But in order to use "state" we have to go back to our original way that we created React components. If
you remember this, when we first did "create React app", we create a class and we do that by saying "export
default" or "export App
extends React.Component"
It extends the "Component" class, and again we can use shorthand here and just say… So now we can just remove
React from here
And this always has a render function that has to return something, which is this
Again, it's just the syntax that you have to get used to. So if I save this - oh, and I made a mistake here, instead
of "export" this should say "class"
So, yeah, "class App extends Component" and then we do "export default App;"
So again we're just declaring a class. I save and we just have something that says "state is assigned
a value but never used"
That's because that's pretty true
we don't use it
So how can we add "state"? Well, in React
we simply do a constructor
You might remember this from when we spoke about objects
And this constructor, in here we can declare the state
We simply say "this.state =", and in here we just put whatever we want our state to have
So if I save this, I get
"'this' is not allowed before super()"
Again, something that you might remember from the advanced objects video in order to use "this"
we have to do this weird thing where we call "super()" which calls the constructor of component
If I do this and save, everything's working fine
And now we have our "state", which is robots and search field, and this "state" as I've said before is what
describes our app
These are the things that can change, and that's what this "state" is - something that can change and affect
our app
And they usually live in the parent component, the component that is the parent that just kind of passes
"state" to different components
And now I can access "robots", not from here, but from "this.state.robots"
And again, just React syntax that you'll have to get used to
All right
So everything is working as expected
And do you see that our state, which is "robots", is now passed down as "props" so "CardList" accepts "robots"
as "props" even though in the app.js
it's a "state". And like I said because "App" now owns "state" that includes "robots"
it's allowed to change it. OK
Now the way we can communicate them, we have these two valleys, and ideally in the search box I have something
called "onSearchChange()", which again is a function that I'm just going to make up
This is just a random name that I've created
And "onSearchChange()" I want to say that every time the input changes, just like we did with DOM manipulation,
we get an event, and within this event I'm going to "console.log" this event
I've created a function, and I want
any time this input changes to trigger "console.log"
So we can pass this actually now. I can say "searchChange=[onSearchChange]", but again because this
is an object we have to say "this." so that it says "this" (which is the "App") ".onSearchChange" is "searchChange"
If I save this and now go to the search box, I now have "searchChange"
as a function, so I can just say, just like in HTML -
Remember in HTML I can do "onchange html", it's an event,
we're just listening to "any time the input changes"
So I can say "onChange="
"[searchChange]"
Let's see if that works
I'm getting no errors
If I go back to my app, I open up the console and I type in something, and look at that!
I'm getting the event. And this is just something you have to remember is that with an event we always
have "event.target.value" which should give us the value of the search term
Let's save that and type in something here
Look at that! We're now noticing the difference as we type
So let's go over one more time what just happened
And again I know this is tough
This took me a while to get when we first started, but this diagram really explains it well
I have my app component
My search box, and my card list. Any time the search box changes, on change I'm going to run the function, I'm
going to call this function
And the way we call it is we add this
Remember how when we did DOM events we defined the function and then every time the event happens it
would call it.
So we are saying every time the onchange event is triggered, call the search change function
And if you remember the search change function which is a prop is the "onSearchChange" function that
is defined in the app
That's how we communicate with the parent
It triggers the event, the parent says "Oh, run this function"
And now this function gets run
But now that I have the value of the search input, I can now directly communicate that search input to
the "robots" list
Let's see how that works
We can create a variable, let's say "filteredRobots", and this will equal the "this.state.robots"
and this "robots", which is the array
- again this is how we access "state" - is going to use "filter", filtering our array
We give it "robots", and now our array will have to return a condition, and the condition is going to be
"robots"
".name" and we're going to do something that we haven't seen before which is "to.LowerCase"
And this is a method that comes with all strings, and it just makes everything lowercase
And this is good for comparisons so we don't have to compare capitalized or lowercase
And if the "name" of "robots", which is now lowercased, "includes" - it's another method and again it's pre-built
into javascript - if it "includes" the "searchfield"
And again we want to do "toLowerCase" in case
Well in case we use capitals or lowercase, it works both ways
And there it is
If the name of the robots in lowercase includes - and this does the comparison -
if anything in the string includes "toLowerCase", well, then only return the robots that returns true
to this. Let's save -
- oh, and you see here the how you get the 'searchfield' there because, well, it's part of the state
I have to do "this.state.searchfield"
If I save this, I get that
"'filteredRobots' is assigned a value but never used"
But don't worry, we can now console log this and see what we get
if I save, and let's go back to our app, and if I search something here, oh, I get an error
And this is an error that is very very confusing
It is tricky the first time
But bear with me here
The problem right now is that the value of "this"
well it's not referring to the "App", because the event happened in the "input", the value of "this" is, well,
the input, and "input" doesn't have "state.robots"
And this is a trick that you always forget, but just keep this in mind as a rule of thumb
With anything that comes from React, so constructor and render are pre-built in React, any time you
make your own methods on a component, use this syntax, so arrow functions, and this makes sure that the "this"
value is according to where it was created, which is the "App"
I know it's confusing
You can up read more about it
I'll leave a resource for it
It's a tough topic to get, but again, rule of thumb -
use the arrows
If I do this now and I click, there you go - I now get "robots"
But here's the thing
Searchfield right now - you see that I still have 10 robots, it's not really filtering anything
And that is because my "searchfield" is always an empty string. In order to update the state
again another rule of React is to do "this.setState", and it's again a method that comes with React
And anytime you want to change state you always do this, you don't do "this.state.searchfield ="
- you never do that
You have to do "this.setState", and within here we just say "searchfield is…" - and again we're using
an object, so "searchfield is now going to be "event.target.value"
If I save this and go back, you see that now everything is being filtered
So I'm changing the state so that the "searchfield" always gets updated
and now we're filtering the robots according to the changed "searchfield"
OK
So one last thing. Looking at this
We have the fact that filter robots is still not assigned, and you're right
If we look at this, we've now communicated the search box with the app, and we have the search field constantly
changing
So now we need to communicate it to the "filteredRobots". What we can do is that "filteredRobots" can now
be used as props instead of "this.state.robots"
So let's do that
Let's move this down here
And now we have access to "filteredRobots", and instead of passing "this.state.robots" we simply pass
"filteredRobots"
If I save this, make sure the search part saved as well
And now I go back. I'm going to close the tab and let's check it out
Look at that
We have our app working
How cool is that
Let's go over it one more time to show you exactly what it does
We have our "App" component that has two states - "robots" and "searchfield"
And because "App" owns the state, any component that has "state" uses the "class" syntax so they can use the
"constructor" function to create "this.state", and this "state" is what changes in an app
It's what describes the app
Remember when I said the virtual DOM is just a javascript object? The virtual DOM is just an object that
collects this entire state and React uses this state to render and pass them down as props to these
components so that these components that are just pure functions can just render
And we always know that the app is going to look the same because, well, they're just simple pure functions
We manage this state in here, the app is the only thing that can change this state
But it can pass down things such as props, so we passed down "onSearchChange" to the "SearchBox", and the
"SearchBox", every time there's an "onChange" on the input,
it lets the app know "Hey, there was a change"
"Run this function"
It runs the function with the event and updates the state of the "searchfield" to whatever we type
Now with the information that we have from the search box we can now communicate to the card list and
tell it "Hey, I want to filter the "robots" state to now have only what includes in the "searchfield"
and instead of passing that "this.state" to our "robots" we just passed the "filteredRobots"
You might be asking yourself "Well, "robots" never really changes, does it?"
"We always just create a new array called "filterRobots" and we always pass that down"
"Does this need to be part of the state"
And right now not really because we just have a hard coded "robots", but when we get later on in the
course you'll see that that's not the case
Most of the time you're getting the users or robots from another place over the internet in which
case we will need "robots" to change from an empty array to an array
after we go and grab all of our users
Whoo! All right
That was a lot
I know, I know it's a lot of information, a lot of new syntax, but as you can see, with a few lines of
code we built a pretty awesome app. In the next video we're going to finish this up and finalize our
app
so it looks as pretty as this
I'll see you in that one. Bye!