- Read Tutorial
- Watch Guide Video
So, the very first thing we're gonna do is import the library. It's the react-html-parser Library. So, I'm gonna say import and the module we wanna bring in is actually called React and this is a component, so it has a real, it's in capital letters and what we're bringing in is code inside of the library itself, so you have to spell it out like this, ReactHtmlParser and it has to be spelled exactly like that from and we're gonna pull in react-html-parser just like that and you can hit save.
blog-detail.js
import ReactHtmlParser from "react-html-parser";
And this library is in our node module, so we can bring it in and now you'll see, this is actually pretty easy, all we have to do is call the library. So inside of content, we can now say ReactHtmlParser, and then this is a function, so we're passing in content into Parser just like this, hit save.
<div className="content">{ReactHtmlParser(content)}</div>
Now let's switch to Google Chrome and you can see all of our code is now HTML code, it's actually rendering like HTML code. That was pretty easy, so that library is a very nice one. We're gonna work with it a little bit more and we're gonna see some of the other options you can use when we build out our summary page but for right now, this is working perfectly.
We have each one of those paragraph tags actually now looks like a paragraph tag and if you scroll up to where I added some of the other features such as having the italicized content, you can see that that is now rendered properly.
Now depending on the font that you went with, some of the HTML code might not change the way you'd expect, so, if you remember, I had a few items that were bolded but this font doesn't actually have that bold style, so that's the reason why you're not seeing that but you can see obviously our paragraph tags are working, our italics are working and this is all working really nicely.
So I'm very happy with this and the other item I wanna take care of is this big ugly empty box here, so as you know, this is our spot where a featured image would go and when we upload a featured image, then this will work fine but when we don't upload an image, it'd be much better if this simply didn't exist, so let's go and update that now.
If you go to Visual Studio Code, we can do two things. I'm gonna start off with the easy way which is to check to see if there is a featured image URL and then I'm gonna use a ternary operator, so I'll say featured_image_url question mark and then if that exists, then I want to render all of this code, if not, I'm gonna use a colon and say null.
blog-detail.js
{featured_image_url ? ( <div className="featured-image-wrapper"> <img src={featured_image_url} /> </div> ) : null}
If I hit Save here, then this is really all that we need to do. If you come back to Google Chrome, you can see the ugly empty box is gone.
If you have an image there, it will still work and we can test this out. If I go to DevCamp Space, since we don't have the image uploading ability in our own app yet, we can do it from here, so if I go to Blogs and scroll all the way down, I'll add a new blog post, it doesn't matter what you put in any of those fields but I am gonna upload an image.
So I'm gonna upload this image, create that record, you can see that that was created and now if I go to the blog, you can see the new record was created and our image does show up. So, if we have an image, it'll show with this nice big banner, if not, it won't show.
Now that is the basic implementation but we can do better and in order to follow React best practices which is something I always wanna show you, we can clean this up a little bit so that we don't have this ternary operator right in the middle of our code and we have something that is a little bit more declarative.
So, what I mean by declarative is that if you were to come or some user, developer were to come and look at this code, it would take them a little while to figure out what's going here. They'd have to first see where the ternary operator started, where it ended and they'd say okay, it looks like they're checking for a featured_image_url and then they have this div with this className, then they have this image and then they're passing it in and if not, then there's null.
This isn't too tricky and it really is fine to use it like this if we want. However, the way that I would personally do this is I would create a dedicated presentation or functional component that'll handle all of this for us, so let's do that.
I'm gonna go into our blog directory, so I'm gonna go into components, blog and I'm gonna create a new file here and let's just call this featured-image- or let's call it actually blog-featured-image.js
and this is gonna be a pure functional component and so, I'm going to use one of my user snippets here and let's call this BlogFeaturedImage and this is gonna take in props 'cause it will take in that image prop and so, make sure you call it props though.
So, this is gonna take in pros. I'm gonna get rid of all the return code in here 'cause I want to write this out from scratch. And let's actually bring in all of this code here, so I'm gonna cut that out and then paste it directly in here.
Now we're not gonna use it exactly like this. Instead, what we're going to do is we're gonna expect a prop and I'm gonna call the prop just img, short for image. So, the very first thing that I wanna do and let's give ourselves some space is I'm gonna check to see if the prop exists. If it doesn't exist, then I just wanna return null just like our ternary operator's doing.
So, I can say if props.img which we'll be expecting and I'm gonna put an exclamation mark at the beginning of this, so what this is saying is this is the same thing as saying if props.img is triple equals to null or something like that, but instead, it's shorthand, you can just say with an exclamation mark this means if this doesn't exist or if it's false, then I want you to simply return null, just like that and so, then our BlogFeaturedImage is going to simply return null, nothing else even is going to get processed in there.
blog-featured-image.js
import React from 'react'; const BlogFeaturedImage = props => { if (!props.img) { return null; } {featured_image_url ? ( <div className="featured-image-wrapper"> <img src={featured_image_url} /> </div> ) : null} } export default BlogFeaturedImage;
Now, if that is not the case which means if we do have a prop with an image, then I can say return and then we can put all of our cool div and image code here, so I'm gonna grab all of this, put it inside of this return statement, clean up our code a little bit and hit save. Now, the one change I'm gonna make here is this is no longer gonna be called featured_image, instead it's gonna be called props.img, hit save.
blog-featured-image.js
import React from 'react'; const BlogFeaturedImage = props => { if (!props.img) { return null; } return ( <div className="featured-image-wrapper"> <img src={props.img} /> </div> ); }; export default BlogFeaturedImage;
Now what we can do is call BlogFeaturedImage as a component, so inside of our blog detail, I'm going to call BlogFeaturedImage and then I'm gonna pass in an image prop and then this is going to be that featured_image_url. If there is no image URL, then it gets caught in that first condition and nothing shows up.
So, the last thing that we have to do here is we have to import this, so copy that code, come up to the very top of the file, say import BlogFeaturedImage from ../blog/blog-featured-image, hit save and let's go test this out.
import BlogFeaturedImage from "../blog/blog-featured-image";
So, if you come back to the page, you can see that if there is an image, it shows up just like we would expect, so, this is working perfectly.
Now, if we come back here, go to Content Page, no image exists and so, no image shows up. So, what we did here was we followed a React design pattern. We followed the pattern where we ensured that the featured image had one single responsibility, so we made sure that the BlogFeaturedImage now has just the responsibility of taking care of the image. If nothing exists, nothing gets shown up. If there is one, then it wraps it up in the div tag and stores it inside of that image tag.
When a user comes to our blog detail component or a developer comes to look at it in the future, this is much clearer on what this is. They don't have to go read a complex multi-line ternary operator. They can simply look at this code online and say I got it, this is a BlogFeaturedImage, we're passing in an image prop and if they wanna know a little more about it, they can go look at that code.
So, this is gonna be much easier to maintain in the long run which I promise you, you will appreciate as you start building out your applications. So, great job if you went through that. We now have a completely functional blog detail page. It shows our images, it shows our content, it parses it as HTML and so, in the next guide, we're going to extend our HTML parsing knowledge and we're gonna start building out summaries on our index page.