Modifying the Posts Component to Render Different JSX Based on Prop
Hi there, and welcome back to the React course. In the guide, we will be modifying our posts component to display different content in our results than it does on the homepage.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

On the home page, it's displaying this.

large

On our results page, it's displaying this.

large

Same kind of format. We need to modify it so it looks more like this. We want to display the associated topics on top, we're going to display the title here, and then we want to display some links with a box.

large

We can easily do this in our posts component by pass in a prop that tells us which one we are on. I'm going to close out of some of these tabs, so all we have are resultsPosts.js and posts.js. I also want to open up recentPosts.js because those are the two lists we're dealing with.

What we're doing is we're returning post in each of these the same way. We have the key in post swapped, but that doesn't matter. What we need to do is in resultPosts.js we just need to pass in a prop that says on each one of these posts that says type...well we'll do it in our recent first.

In our recentPosts.js, let's just go to Post and say:

recentPosts.js

    renderPosts = function() {
        const posts = this.props.recentPosts.map((post, index) => {
            if(index < 3) {
                return (
                    <Post type="recent" {...post} key={index}/>
                )   
            }
        })
        return posts
    }

Now in our resultsPosts.js, we will say type="result".

resultsPosts.js

    renderPosts() {
        const posts = this.props.posts.map((post, index) => {
            return <Post type="result" key={index} {...post}/>
        })
        return posts;
    }

So we have two types: result and recent now. In our post.js we just need to render different content based on that. So let's say:

post.js

render() {
        if(this.props.type == 'recent') {
            return (
                <li className="recent-post">
                    <div className="recent-post__title">
                        {this.props.title}
                    </div>
                    <div className="recent-post__topics">
                        {this.renderTopics()}
                    </div>
                </li>
            )
        } else if(this.props.type == 'result') {
            return (
                <li className="result-post">
                    <div className="result-post__topics">

                    </div>
                    <div className="result-post__title">

                    </div>
                    <div className="result-post__links">

                    </div>
                </li>
            )
        }

Super simple stuff. Now we just need to render each of the topics, titles, and links. We already have rendered topics. So let's just copy this call, and put it in the topics. Now we need to just reference the title like we did up here. So let's say:

post.js

render() {
        if(this.props.type == 'recent') {
            return (
                <li className="recent-post">
                    <div className="recent-post__title">
                        {this.props.title}
                    </div>
                    <div className="recent-post__topics">
                        {this.renderTopics()}
                    </div>
                </li>
            )
        } else if(this.props.type == 'result') {
            return (
                <li className="result-post">
                    <div className="result-post__topics">
                        {this.renderTopics()}
                    </div>
                    <div className="result-post__title">
                        {this.props.title}
                    </div>
                    <div className="result-post__links">

                    </div>
                </li>
            )
        }

Now for the links, we need to do something similar to the renderTopic, so let's just save this and see if it's working. Let's go to our app. Let's go to results, let's type in something for results, and yes, so we have that on top now. We have the associated topics and then we have the title.

large

Now what we want to do is get those links in there like you see in here. It's going to look a little different. We're going to add in the div for the box but we're not really going to see anything since we're not going to apply styles.

So we'll just add in those box divs, but it's not really going to look like that. We're just going to see the titles for the associated topics. Let's go ahead and go to our app here, and then let's go back to the code. Let's just make a call to this.renderLinks().

post.js

render() {
        } else if(this.props.type == 'result') {
            return (
                <li className="result-post">
                    <div className="result-post__topics">
                        {this.renderTopics()}
                    </div>
                    <div className="result-post__title">
                        {this.props.title}
                    </div>
                    <div className="result-post__links">
                        {this.renderLinks()}
                    </div>
                </li>
            )
        }

Let's make that function right below renderTopics. What we need to do is hit return and say renderLinks, and basically do the same thing except for call the links. Let's check the response here. So post_links and then it has these links in here.

large

So it's a little bit different, we might have to dig a layer deeper. That's actually pretty easy. Let's go to our app here and instead of just saying topic we'll say like topic.link because you'll see we have an object within these.

Let's go ahead and search rails in Postman just so we can get more post_links. I'm trying to look for one that has more post_links. I'm just going to type in something like JavaScript. I guess they all have 1 post_link. One of these has to have more than 1. I'm going to type in results just to see if we get anything.

This one has more. Basically, the difference between the associated_topics and post_links is the associated_topics is just a collection or an array of strings whereas post_links is a collection or array of objects.

large

We need to get the object and then say .link_url. Let's go ahead and do this. Let's say:

post.js

    renderLinks() {
        let links = this.props.post_links.map((post_link, index) => {
                <div className="post-link" key={index}>

                </div>
        })
        return links;
    }

Now back in our design, we need a couple of things. We need these, so we need a div containing everything, which is the post_link. Then we need a div for the box, we need a div for the link, and then within that there we can have an actual link. So two more divs and an a-tag.

Let's put the div in here for the box and put the div here for the link. For the first box for the box when we need a className. Let's say:

post.js

    renderLinks() {
        let links = this.props.post_links.map((post_link, index) => {
                <div className="post-link" key={index}>
                    <div className="post-link__box"></div>
                    <div className="post-link__link">

                    </div>
                </div>
        })
        return links;
    }

Within the box, we don't need anything because it's just going to be that gray box. Our design doesn't really display. I would assume that you would want an image there, but our response doesn't include any images. So we'll just keep it as a gray box, and then in the future if the response changes we can put an image in there.

For the post_link we need to return an a-tag that displays our link. We could just say:

post.js

    renderLinks() {
        let links = this.props.post_links.map((post_link, index) => {
                <div className="post-link" key={index}>
                    <div className="post-link__box"></div>
                    <div className="post-link__link">
                        <a>{post_link.link_url}</a>
                    </div>
                </div>
            )        })
        return links;
    }

Let's head back to our app, and let's see if we are rendering it. Let's type in rails, and you'll see that nothing has changed.

large

That's because we're not returning this JSX. We need to cut this using command + x, and the type in:

post.js

    renderLinks() {
        let links = this.props.post_links.map((post_link, index) => {
            return (
                <div className="post-link" key={index}>
                    <div className="post-link__box"></div>
                    <div className="post-link__link">
                        <a>{post_link.link_url}</a>
                    </div>
                </div>
            )
        })
        return links;
    }

So we're actually filling the links up with JSX objects to be rendered. Let's go back to the the app, let's type in something like rails, and you'll see our links. Now, these are way too long.

large

We could write an expression to take some words out of here and make us link titles. We'll do that after we build the app if we do it at all. Right now all we need to do is say useful link.

In the design, it has these like Episode 86 plotting points on a map from scratch. Our response clearly doesn't provide us with that clean of data for these postings. All it does is give us a link. We'll have to see what we do with that, for now, we should just put useful link.

large

What we need to do is actually make it go somewhere too. So we need to say:

post.js

    renderLinks() {
        let links = this.props.post_links.map((post_link, index) => {
            return (
                <div className="post-link" key={index}>
                    <div className="post-link__box"></div>
                    <div className="post-link__link">
                        <a href={post_link.link_url}>Useful Link #{index + 1}</a>
                    </div>
                </div>
            )
        })
        return links;
    }

The reason we're saying + 1 is because if you just leave it at index and then render that in the page it's going to start at 0. Arrays started 0, so what we want to do is just say index + 1 so it will start at 1. Let's go back here, let's search for rails, and you'll see we have Useful Link #1.

large

I'll search for results again so that we can get all of those links. So Useful link #1, 2, and 3, and it looks like it's rendering the data we want. We have it all and it's working properly. I think that finishes off the functionality of our application.

large

We have all the functionality you need. We go back to the home we have our recent posts, so I'll check that here. We go back home, it fetches a recent post. We search, it shows our posts. We search in here, it shows our posts, but you'll notice that this data is different.

If I go back here and I search Python, it's automatically different in our app. When we go home, keep note of what this looks like, search Python or results or something, it changes after we get there. So I guess there's a little bit of functionality we still need to add and that's why we need to fix that.

large

We also need to make it so when we hover on the tile it shows these rather than automatically showing them. We don't want to have it so you click it. We just want it so when we hover over it it shows these titles.

We have a couple more pieces of functionality. It's the hover effect and the callbacks to fix the rendering of this when we are at home and we search something like Python. We want it to change before we get here. We want it to load so to speak.

Let's commit our code. I'm going to say git status, git add ., and then let's say git commit -m "modified post component to render a result post and setup render links" and that's it. This was a pretty long guide. We got a lot done in this guide.

We'll finish off the functionality in the next guide with the hover effect. What we'll do is we will make the next guide about the callback so when we go to a localhost, I reloaded the page so it is going to be different, or there's not going to be any data, but it is still going to take a second to load.

Basically, what we're going to do in the next guide is make it so it loads before we get to it. After that, we will implement the hover effect. Then we'll be done with the functionality completely and we will hop right into the styles and finish off the app. I'll see you then.

Resources