- Read Tutorial
- Watch Guide Video
I know the last video was pretty long and so I hopefully will be able to fit the rest of it in this one and allow you to be able to finish it relatively quickly. But some of the concepts that we're going to be touching on are pretty important so I'd definitely recommend that you work through them play with the examples play with the code that we're going to build.
Because they're going to allow you to build out much more advanced behavior into your applications later on. So each one of these concepts is so foundational to react that if you struggle with these and it's fine to struggle the first time but if you do not struggle to the point where they start to make a little more sense then when you get into more advanced topics it's going to be very hard to understand what's going on.
So we've talked a little bit about props and we're going to continue that discussion. So we're going to keep on and we're going to have another example where we send props. We have been working with react tools, these are very helpful. They give you access to the virtual DOM in react they show you the props and the state.
And then we also have already talked a little bit about state how we can add it to a component and later on we're going to see how we can manipulate it on the fly. Now we haven't discussed a ton about this but we have already been using it and the more times we use it the more it's going to make sense on what it is and we're going to keep on talking about it.
Now that we've not covered this yet, so let's go on and let's talk about this first and that's going to be functional versus class components and so that's going to be one of the main topics that we discuss next. We have discussed component based architecture, each one of the elements that we've been working on has been a component and we're going to keep on discussing that. We've seen how we can use code organization to be able to separate our components into different parts of the code base and we'll keep on talking about that in this guide.
So we're going to review each one of these items(Props, React Tools, State, This, Functional vs Class components, Component-based architectures, Code organization) we've covered them all already. But let's keep on diving in and seeing more examples because if these are not making sense to you now I really think one of the best ways of having them be more clear in your mind is by approaching them at different angles.
So let's start with that. I already have the server running from our last guide and now let's jump into our journal_list.js
so in the last example when we wanted to call the JournalList component
from app.js
we added it in a completely different file and we imported it. That kind of speaks to how we wanted to learn about code organization and how we created this journal's directory and then from there we created a JournalList file and then we put our component in it but that is completely optional.
So right here let's imagine that we don't want to create a file we will later on because that's just really a best practice but let's just imagine that we don't want to do that. Instead, we have a pretty basic component here and we want to use it inside of our JournalList. So this is going to be where we start talking about the difference between functional and class components. So because you can see right here the word class that means that our JournalList component is a class component. It maintains state that is really one of the rules of thumb if you need to maintain state then you have to use a class component or at least that's usually the standard operating procedure.
But now we have another component because we're working on building out a little Journal program it makes sense to have a JournalEntry. Each one of these data items is a JournalEntry and so we want to have a component that renders that on the screen. So I think it makes sense to be able to use a functional component for that because all it's going to do is render the entry on the screen.
So in order to do this I'm going to start by just saying const JournalEntry and it's important that any component that you use in react that you use of this kind and naming structure where each word has a capital letter so it starts with a capital letter so JournalEntry
should be spelled out exactly like this. But instead of making this a class and a component I'm just going to say const JournalEntry = props
because props is the argument.
We do want our JournalEntry to have access to props and let's just see what happens if I don't pass this in. Remember part of these deep dives is not just to build a project out, this code is really code that you can just use for reference later on. The top goal that I have is to help you understand these concepts and one of the ways that I personally understand complex topics the best is by taking examples and not just walking through the step by step guide but really throwing that right outside and being able to rip apart everything that we build to understand exactly how it works and so that's what we're doing here.
So I will eventually pass props to it but for right now let's just create a functional component and see what happens. So inside of this, I'm just going to create a return statement, so inside of here let's just return a div and then inside of here we'll do an H1 I'll say hi there for my heading and then let's do a paragraph tag with some amazing content close off the paragraph tag and then let's close off that div.
journal_list.js
const JournalEntry = () => { return ( <div> <h1>Hi there</h1> <p>Some amazing content</p> </div> ); };
So that is a very boring and really pretty useless component until we add our props to it, it really doesn't do much besides just render this div with an H1 and a paragraph tag. Then what we can do is if you come down here into our full JournalList component let's get rid of, I shouldn't say let's not get rid of, I want to keep those headings there so that you can see the way that works.
Now let's come down here and under our heading let's call our JournalEntry so I can say JournalEntry. We're not passing it any journal props or anything like that. And let's also wrap this all up in a div just like this.
journal_list.js
render() { return ( <div> <h2>{this.props.heading}</h2> <JournalEntry /> </div> ); };
So now instead of just returning that heading, we're now going to get this JournalEntry which has a heading of h1 and a paragraph tag. Now let's switch back to Google Chrome and this is working.
So far this is completely functional and this hopefully will give you even more of a base case scenario for understanding how a functional component works where you can create a component just like JournalEntry and then you can call it from within another component like we've done here on line 34. And because this component right here JournalList because this is called twice right here that is a reason why we have two of them, we have our list 1 and we have our list 2.
But that's not really that helpful, so let's come here and let's start making this dynamic. So now instead of just calling JournalEntry which is a regular javascript function instead of calling that just with no arguments let's pass props into it. So now if we do that, what I can do is I can make this content dynamic so I can say props.
and then I'll just say title
and then inside of this I'll do something similar so I'll say props.content
.
journal_list.js
const JournalEntry = props => { return ( <div> <h1>{props.title}</h1> <p>{props.content}</p> </div> ); };
Now this by itself won't help us out much because now we actually have to pass some content in. So, I'm gonna come here to JournalEntry and the way you can pass these props in is you can say title and then I'll start off with this "Some title"
and then for content our content prop will be "More content"
.
Save and let's see what this looks like. OK, that's working perfectly. So now notice that this is all dynamic and if we come and inspect this in the virtual DOM and I'm in the react helper here now you can see our JournalList has nested items and it has this JournalEntry now and we're passing in our props.
So these are the properties it's just we're passing in content and title which are just some strings and those allow us to make that functional component dynamic. So I wanted to put this here, I wanted to put this in this file, to begin with one so that you didn't think that every component needed to be in a file. Now it should be in a file, I still have not had a situation where I did something like this just because I don't really think it's logical to have a JournalEntry component here sharing the same file it makes much more sense to put this inside of its own file.
However, the entire purpose of this deep dive and all the deep dives is to be able to understand how the system actually works not just follow a bunch of step by step guides. So we have a JournalEntry functional component and the other reason why I wanted it here was so that you could see the difference between a functional component and a class component.
So see how much more basic this is, this does not have a render method. So you can see in our class component we have a render method that is something that every component in React needs. This doesn't need it(const JournalEntry), this just returns some jsx code. So we have a div and that's wrapping up a heading and a paragraph tag. Now a functional component though can take props.
Now if you're wondering how in the world does it have access to props? Because technically when we're calling JournalEntry we're not really calling this like a regular method. So you know in vanilla javascript you want to call a method I'll say some function and then you want to pass it some data. So someOtherFunction so if you wanted to do that and you wanted to pass in some data you'd call it like that.
someOtherFunction('some data')
And as you may notice right here that JournalEntry is not being called like that and that's because a JournalEntry in this sense whenever you declare a function an anonymous function and then you start it with capitals and then you set it equal to props or like you saw you don't even need to have props as an argument. But just when you use this kind of structure in a file that imports react. What react is going to do is it's going to look at this and it's going to assume that you want to create a functional component and so what that means is that you don't call that functional component like this someOtherFunction('some data') but instead you call it from within the render function.
So here we have access to the JournalEntry component and we could also copy this so I could create a few of these and say some other posts and here we'll say yet another title let's save this
journal_list.js
render(){ return ( <div> <h2>{this.props.heading}</h2> <JournalEntry title="Some title" content="More content" /> <JournalEntry title="Some other posts" content="More content" /> <JournalEntry title="Yet another title" content="More content" /> </div> ) }
switch over and now you can see we have some title some other post and yet another title.
And so all of this is dynamic and then it was also passed to that second call to our journal_list so that's kind of a basic way of understanding how the difference between a functional component and then a class component.
Now because of the way that you typically are going to want to structure these I would not keep this JournalEntry here. So instead what I would do is I'd come over here create a new file and I'm going to call this journal_entry.js
. Now inside of here, I'm not going to add all this boilerplate code. Instead, I'm just going to grab this code
journal_entry.js
const JournalEntry = props => { return ( <div> <h1>{props.title}</h1> <p>{props.content}</p> </div> ); };
come over here and paste it in. Now you can it save here and then you can come up to the top and now import this but I'm going to show you something that's a little bit tricky that won't work here. So I'm going to import it, I am going to use the curly brackets because you need to do that and I'll talk about that in a second and why we need to. So I'm gonna say import JournalEntry from and then just dot slash journal_entry.
journal_list.js
import { JournalEntry } from "./journal_entry";
And you may think this wouldn't work because we're importing this JournalEntry our path is right and if you come over here to journal_entry.js everything here seems like it should be working. But now, well it's not. And if you come to console you'll see we get all kinds of fun errors.
So that is not what we want to do. So what's going on? Well, the problem is that we are treating this file(journal_entry.js) and we're treating this code here like it's just regular vanilla javascript code and that is not what we want to do, what we actually want is to treat this like a functional component. So what we need to do is we need to import React. So I'm gonna say import React from react.
journal_entry.js
import React from "react";
Now, if I come back here let's refresh and let's see do I have a typo. Oh yes, another issue you need to export this as well.
journal_entry.js
import React from "react"; export const JournalEntry = props => { return ( <div> <h1>{props.title}</h1> <p>{props.content}</p> </div> ); };
OK, so now we need to export this because this at the end of the day still is a javascript module and now everything is back to working.
So we now have implemented the right kind of organization with our code. So why didn't this work before? It's because if you remember back when I said that this JournalEntry is called differently than a normal javascript function. Well we were calling it that way here. But when we didn't have react and we weren't importing that from this file react didn't realize that JournalEntry was a functional component. It started treating it just like a regular component.
So here now we are exporting it as a module, we imported react and so now it treats any kind of function like that. It's going to treat it like a functional component and then it can be treated that way in all of the other files.
Now one other thing I want to bring up because we ran into a little bug in the last video with this. Notice the difference in the import statements. So right here I have a JournalEntry that I am importing with the curly brackets syntax and then here in app.js I am importing JournalList without it.
journal_list.js
Import { JournalEntry } from "./journal_entry";
app.js
Import JournalList from "./journals/journal_list";
The reason is because when you export a class in JavaScript specifically in the latest version of JavaScript and you say export default class then what JavaScript does is it automatically binds this name of JournalList to that file and when you access it you can call it without having to do the curly brackets syntax.
Now here we're saying export const JournalEntry
and because of that we need to import it with the curly brackets and so what this means is if we wanted to put other functional components here. So say that we had 5 types of components and for some reason or another we did not want to put them in separate files. Well, you can simply list all of them right here with the import statements. So I could say import JournalEntry and if I had some other function so let's just copy all of this and say export const SomeOtherFunctionalComponent
and I wanted it to do something very similar to what I'm doing right here. Let's come over and after I say JournalEntry and I import that lets I also want to import SomeOtherFunctionalComponent.
Obviously you can see there's nothing special about this name and I'm just bringing it in. Let's come down here and give us some space and now I can say some other functional component and let's pass in the props. So Some other I'm not gonna type the whole thing out and then some content, other content and let's close it off just like we did with journal entries and I'm going to get rid of these two just so you can see these right next to each other.
So that's saved, journal entries is saved, so even though we have it named like we have here because we've exported this other function we're going to have access to it. So if we come over here you can see that we have some other.
So we have a exactly the same access and we can call this component exactly like how we did for our JournalEntry.
Now, I don't usually have this kind of structure, just because they think it can be a little bit confusing. So imagine a scenario where you need to work on this SomeOtherFunctionalComponent later on, if you had named this file journal_entry then you're going to have to spend a little bit time searching for this other component right here.
So usually I'd create a separate file and import it manually. But I just wanted you to see there's not any magic behind this. All we're doing here is we're creating a functional component and then we're exporting it and then we're importing it in another file that's all that's going on here.
Now, this is all we're going to do for this entire project for journal_entry. So I'm going to get rid of that we don't need to have it open.
Let's remove this SomeOtherFunctionalComponent and let's also remove our call to it. Hit save and come back here to our localhost everything is back to working and it's working properly. So we've covered a lot already and I just have a few more things I want to show you, so thank you for hanging there in there with me I know this is a lot of content and we're covering a lot of topics but hopefully, you'll get a lot out of it.
The next thing that I want to cover is how we can manipulate state. So right here we've set the state.
And that's very helpful, we have content that we have access to right away but we are not really doing anything with it. We technically could have just hardcoded everything in with the current situation but instead what we want to do is have the ability to make our entire system dynamic and so let's move on to that next.
So I think one of the most straightforward things to do would be to create a button that is going to clear everything out. But before you do that I just remembered that we're not actually showing any of our light data. So we need to build a method that is going to build up each one of these objects and then it's going to show that on the screen.
So in order to do that I'm going to come into the render method, so this is going to be right below where we're calling render and I'm going to create a variable here called const journalEntries
. This is going to be a new variable and it's going to store the data.
So it's going to store the data but it's going to store it in a way that the browser can actually or I should say that react can convert into something that the browser can show. So I'm gonna say this.state.journalData
. So remember we set that right when the constructor loaded we set our state equal to the rawJournalData so it set it equal to what we have right here.
So I have journalData and then I want to call the map function on that. Now map takes a function as an argument so I'm going to use a variable called journalEntry
. There's nothing special about this, I could have just as easily called this asdf or X or anything like that but I think the journalEntry makes the most sense because what map is going to do is it's going to iterate over each one of the items in our rawJournalData here and then it's going to give us access to each one of those objects.
So I think journalEntry is a good name for it and so I'm gonna use an arrow function and then curly brackets so what we do inside of here is going to be returned and stored inside of this journalEntries variable. So we need to make sure we return this so I'm gonna say return and I want to write some jsx here and I'll say div key equals and all key is, is it's something that we give react so they can keep track of any type of collection because if we just passed in say a thousand journal entries then react wouldn't really know the difference between the first and the twenty-third one and the forty second one in the thousand.
So what we need to do is to give it a way of keeping track of that. So for right now I'm just going to say <div key={JournalEntry.title}>
and now we're going to pretend like the title is always going to be unique. That's something to keep in mind, you need to make sure that whatever uses a key is going to be unique. Usually what you'll do is you're typically going to be communicating with some type of API and that API will send you some type of unique identifier.
So if this JournalList was pulling from some outside API like a python flask API or a rails one then that API would return a unique identifying number from the database and so that's what you'd usually use. But we're just going to use title and now inside of here, this is where we're going to call our JournalEntry component. So this is going to call our functional component and then we can pass in our props just like we did down below except now we're not going to hard code everything in so I'm gonna say title={journalEntry.title}
.
So we can use this dot syntax because we're working with an object and then we want our content to equal the same thing. So we'll say journalEntry.content and then let's use a slash and then close that off. Now if I hit save prettify is going to rearrange it nicely for me. So we have our JournalEntry and that's should be all that we need to do.
journal_list.js
render() { const journalEntries = this.state.journalData.map(journalEntry => { return ( <div key={journalEntry.title}> <JournalEntry title={journalEntry.title} content={journalEntry.content} /> </div> ); })
So now that we have that in place what we can do is come over here get rid of this hardcoded JournalEntry and now just call that variable. Because remember journal entries are variable because we use a map that is a way that in react where you can build up a collection of jsx code like we have here in our render and then you can just call it. So I can say journalEntries and now let's hit save.
So if I hit save let's come back and see if it's working and yes this is live data.
We have post one, post two, post 3, post 4, and then we have this and we have access to it in both components so that is working really well. And in fact let's get rid of that second component just so we don't have too much data on the screen at one time. So now you can see we just have that first list and we have our live host now. So this is really pulling from live data now instead of our hardcoded props.
So just like you can see whenever you're working with props you have the ability not to just pass them you know one at a time you can build up an entire collection and then pass them in dynamically like we have right here. Now if you go into the react tab and come and look at it if you click on JournalList and you can see that we now have JournalEntry's and each one of these has its own set of properties.
So our props here are content: "Post content"
and then title: "Post One"
. So I'm really happy with this, this is all coming along really nicely.
Let me do one more thing here that you may like, so instead of having to keep on scrolling I'm going to split the screen here in the browser and now it's going to be a little bit easier for us to navigate and see everything all on one screen.
And I have some good news we are very close to being done! You've been doing a great job going through all of this. We only have three more methods to build out. The first thing I'm gonna do is this is going to focus now we're transitioning and we're going to focus on how we can manipulate state inside of react. Now if you're coming from a jQuery or a vanilla javascript background you may think that if you wanted to remove all these elements that you would add some type of button it would have an event listener and then from that event listener, you would have some type of function that would go and find all the elements on the page and then it would remove those.
In a regular application that would be the correct process to follow. But remember react uses a virtual DOM. It does not use the same Dom that you have with regular HTML sites. So what we're going to do is we're not going to go and select these items, instead we're going to work with state. So we know if you switch back to the component. We know that this state meaning the state portal this object and this is also going to touch on what this represents too. Remember when we had two JournalLists there?
Well, the this for journalList one represented only the state for that component. The this for the second one for that list two represented the state for that second component. That is something that's very critical to understand is that this is in reference to the implemented the instantiated component. And so like I said we will talk about this throughout this entire course because it's one of the more complex topics in all of react. But just to give you a little idea that is really what it represents.
So now that we have that in place let's go and let's see how we can manipulate the state with a button. So I'm going to create a function here called clearEntries. It's just going to be a regular anonymous function which means I'm just going to store it in a variable. It's not going to take in any arguments and then inside of that arrow function I'm going to say this.setState
. And then inside of it I'm going to set the journalData because if you look up top you can see that it's stored in an array.
So what I'm gonna do is say this.setState
and I want you to take your journalData and guess what I want you to do. I want you to take it from having four objects to now just being an empty array.
journal_list.js
clearEntries = () => { this.setState({ journalData: [] }); };
So this by itself doesn't do anything. Now we need to actually call this function and so the way we can do that is inside of our render function I can now create a button. So I'll create a button, so I'll say button and then I'm going to create a click listener.
So I'll say onClick =
. Once again we're going to talk about this. So use curly brackets and then say {this.clearEntries}
now because we're binding this I do not have to say clearEntries and then pass it in as a function. Instead what I can do is because clearEntries technically is a variable it's a function that stored inside of this variable. So all I have to do is say this.clearEntries and then react is going to take care of the rest for me it's going to then call that function automatically. And so from here, I can see a clear journal entries and then close off that button.
journal_list.js
return ( <div> <h2>{this.props.heading}</h2> {journalEntries} <button onClick={this.clearEntries}>Clear Journal Entries</button> </div> );
So if everything works then if I click on this button it should remove all of the journal data. So now you can see we have this Clear Journal Entries button
and if I click it all the entries are gone.
So that's working perfectly. So the process that occurred right here is that we started when the page loaded. We started because the constructor function is called right away with all of our raw data and this was stored inside of our state object where we have journalData it stored the raw journal data here and that is what existed in our state.
But then what we did is we said okay we have this button. If you call it if you click this button, then I want you to call this function of clear entries and then this is what is very important. We are altering the state, we're setting the state to something different. Notice there is no page load or anything like that, so if I hit refresh here all of our data's back don't worry none of your journal entries are gone.
And if I click this Clear Journal Entries what happens here? There's no page-load or anything like that in a traditional application like saying a Rails application or Python Django app. If you click a button the default behavior is it'll try to navigate to another page but with react and angular and view in these javascript frameworks what they do is that they simply will go and update the state on that page.
And so that's all that happened, is if you ever built out some kind of console application where you had an array and then you cleared it you delete all the items that's what we did right here, that's what that button click allowed us to do. We updated the state so that's fine but that's only one part of it.
Let's build out a couple of other functions and then be able to call them just so you can see the way that this works. So I'm just going to copy this clearEntries statement because we're going to be working with some pretty similar types of behavior in all of these.
So in addition to setting one item so right here we just cleared the journalData value but we also can change other values. So let's change is open here so I want to say is open and set that equal to false.
journal_list.js
clearEntries = () => { this.setState({ journalData: [], isOpen: false }); };
So all I'm saying here and you could call this isOpen you could call it whatever you want but I want to keep track of if this element. So if all of these different journal entries if they are open, if they're showing or not. So what I can do is change this state option as well. And so if it's false I'll be able to check that later. Because we're also going to build a method that goes and it toggles the state so we're going to create one that clears them, one that adds them back in and then we'll create one that you can just keep clicking and it's just going to slide the values in and slide them out and you could do it a million times if you have that kind of time and are really bored.
So we have clearEntries and it's going to clear out the array and it's also going to set isOpen to false. Now let's create a function here called showAllEntries. And then what this is going to do is it's going to take that journal data and it's going to kind of reset it a little bit. So now it's going to say that I want that raw journal data back and then I also want to make sure that isOpen is now set true.
journal_list.js
showAllEntries = () => { this.setState({ journalData: rawJournalData, isOpen: true }); };
So let's save that and coming down here we need to add another button. So instead of clearEntries this is going to show all entries.
journal_list.js
return ( <div> <h2>{this.props.heading}</h2> {journalEntries} <button onClick={this.clearEntries}>Clear Journal Entries</button> <button onClick={this.showAllEntries}>Show All Entries</button> </div> );
Now let's test to make sure that this is working. You can see we now have this other button clear journal entries closes them so it hides all of them, it doesn't really hide them that's not the right word to use, it literally removes all the elements from that state, so it removes all of them from that array.
And if I click Show All Entries it brings them all back, so it populates them.
Let's come in here into our tools just to see all of this. You can see that we do have access to see in the state of our journal data.
Now if we come here and we clear all of those now you can see that our array has new items.
If I click Show All Entries we're back to four and it's also toggling this isOpen feature right here. So you can play around with those and see exactly that everything is changing.
Now I only have one more thing to add in and then you're going to be done. You can go eat or whatever it is you want to do. So I'm going to create a function here called toggleStatus, which once again is just gonna be a regular anonymous function. It's not going to take any arguments just like the others. And inside of here it's gonna have a little bit more code because what I want to do here, is I want to check to see if this.state isOpen then I want to perform one task.
I want to say this.setState
and then I want to update that journalData and I want to empty it out so I'm going to send it to an empty array and then I want to say isOpen and then I want to set that to false as you may or may not have noticed. We're doing exactly what clearEntries did. And I'm also going to do the same thing right down below some going to copy this and put it inside of the else statement and then close it off and yes everything there is working and accurate.
journal_list.js
toggleStatus = () => { if (this.state.isOpen) { this.setState({ journalData: [], isOpen: false }); } else { this.setState({ journalData: rawJournalData, isOpen: true }); } };
So now we just need to call our last button so instead of Show All Entries. Now we are you going to say toggleStatus and we can say Toggle Entries or whatever you want to call it.
journal_list.js
return ( <div> <h2>{this.props.heading}</h2> {journalEntries} <button onClick={this.clearEntries}>Clear Journal Entries</button> <button onClick={this.showAllEntries}>Show All Entries</button> <button onClick={this.toggleStatus}>Toggle Entries</button> </div> );
Coming back we have toggle entries, if I click it it removes all the items from the array and just you can be completely sure that it's working. You can watch here on our data tab and click it again isOpen is true we have four items.
Click Toggle Entries and everything gets removed isOpen gets changed to False
and you can keep doing and it will keep on updating that value. So it really is just a kind of an intelligent wrapper around these two. It keeps track of if they're showing or not and then based on that it allows you to either clear out or add the items back in. So that is everything so we just covered everything in section one that I wanted to cover.
We have walked through props, the react tools, state, this functional vs class components, component based architecture, and code organization. I highly recommend that you go through this project code. Play around with it, experiment, see exactly when you change one piece of code how it affects the project and what shows up.
Because that's going to be the way that this really starts to solidify in your mind and that you really start being able to understand it so that you can use it in any projects you want to build.