7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial

Next lesson playing in 5 seconds

  • Overview
  • Transcript

2.6 PageList Component: Listing Pages

In the previous lesson, we created the page list component, which allows us to create new pages in our database. However, we're not currently displaying a list of those pages, so that's what we'll do in this lesson. Let's start by adding a few state properties. When a user initially loads the page we're going to have to make a request to Firebase to send us the current list of pages. So for a short time, there's gonna be no pages to display. And before those pages come, we want to display a loading message, so that the user knows that the page list is coming. So the first state property we'll create is loaded and this will be our flag for knowing whether or not the data has initially loaded. Of course, this will be set to false by default. Next, we're going to have a pages state property and this is going to be our object full of pages that we want to display and this will be an empty object for starters. Now you might wonder, why can't we just use the existence of the pages state property instead of having to actually have a loaded flag? And of course, the reason for this is because it's possible that there are no pages yet, if this is a brand new Wiki. And in that case, we don't want to display the loading message forever. We want to display the correct thing, which would be an empty list. So we're going to use that loaded flag to distinguish between an empty list and no pages loaded yet. Now we want to load the pages from Firebase as soon as the component mounts. So we can include a componentDidMount() function here and this will be run after our component mounts. Within this function, we'll call API.pages.on and we'll listen for the value. Now we did this already on the server side where we did users.once and listened for the value once, so we could just do a single read from our database. However, here we're doing pages.on. So this is actually wiring up a long-term event handler, if you will. Every time the list of pages in the database changes, our page list will be sent the new data. Now our callback here takes a snapshot, I'll just abbreviate that to ss. And within this function, we're gonna call this.setState. We'll set the pages value to the snapshot.exportvalue, which will just convert our snapshot to our raw adjacent data. If there's no value at all, then you'll just set that to be an empty object and then we'll set the loaded property to true, so that our component knows the data has loaded. Now we want to actually render our list. So within our render function here, let's create an array of items. We can get the keys for each one of the pages by doing Object.keys on (this.state.pages). We saw in the previous lesson how Firebase gives each one of our pages a unique ID and those are the IDs that we're getting a list of here, then we'll map over those keys. And for each ID, we'll return a list item. Now of course, it's not just gonna be an empty list item. First, whenever we have a list of items like this, react requires us to give each one a key and so we can use that ID value as a unique key for each one of our list items. Then within this list item, we wanna have a link to the actual page. So that when the user clicks it, the page will load up on the right hand side of the screen. Now if we used a regular anchor element here, then the page would actually reload and the new page content would be loaded in on the right. However, we don't want to reload the whole page, we just want to navigate within our react-router. So the react-router gives us a link component that we can use here. Now we'll need to import this link component. So I'll say, import {Link} from 'react-router'. Once again, we'll have to use destructuring to get that link component. Now back here in our map, this link needs a couple of properties. We we want to link to the page route and this is the page route that we created initially in our app.js file, but we're gonna have to recreate it, because you might remember we deleted it. So we're linking to the page route and we need to give it some params. Now when we're using the params property here, we pass an object to the react delimiters. So that's why we have two sets of curly braces. And in there, we're going to set the id to the id. Now this is the id that is of course, the token on our pages wrote. You might recall when we created that pages route, we set the path to page/:id. That is what our id parameter here is referring to. Then of course, we'll create our link closing tag. And inside of this, we can set this.state.pages[id] to get the individual page and then we can say, .title. Now as we saw previously, we only want to render a list of items here, if our data has loaded. If the data hasn't loaded, we want to display a loading message instead. So let's put this inside a ternary expression. We'll say, let items = and then we can say, this.state.loaded So if this.state.loaded is true, we will render the list items. Otherwise, after a colon, we'll set items to be an array with just a single list item inside of it. We'll give that list item a key of loading and inside will have an emphasis tag and we'll just set the text loading. So now at the end of that process, items will either be our lists of actual pages or a single list item that says, loading. So inside of our template at the bottom in the return statement, let's add an unordered list and we will interpolate the items array Inside that unordered list. If we come back to our page and refresh it, you can see that we get the loading text there in our unordered list. However, it's not actually going away, because we're having a problem rendering our list items and this is because we cannot find the route named pages. That's actually correct because we deleted it. So let's go back to our app.js file and we'll add a new nested route here. We'll give it the name of page and we'll the path to be /page/:id. Finally, we'll set the handler to be {Page}. Now of course, we want the handler to be page. However, we don't have a page component yet. So for now, we'll just set it to app, because we have that component. Now if we had back to the browser and refresh the page, you can see that for just a second there, we see the loading and then we see dogs and cats, which are the two pages that we have created already. I can even add a new page here say, fish. And you can see that right away, it is added to the list, because we are listening for the Firebase value event on our list of pages. Excellent. So now we can display a list of pages. The next feature we want is actually viewing an individual page on the right side of our screen here. So we'll start that feature in the next lesson.

Back to the top