How to build a related posts component for your React blog

How to build a related posts component for your React blog

Some blogs have these related articles or posts sections where visitors can have a preview at more content after they just read a post. That's what I wanted to create for my personal website which is built with React (Nextjs) and in this article I want to show you how you also can do it for any other react application.

Related Posts Component

The keypoint to be able to show related Posts is that you somehow have to create a relation between the posts which doesn't exist yet. All my posts have

  • a title,
  • a description
  • a date,
  • tags and
  • an image.
md
Copy code
---
title: "Post about Web-Development with React"
description: "This is a sample description for the post."
date: "2022-05-02"
tags: ["React", "Web-Development"]
image: "../image.jpg"
---

I decided to use the tags to create a relation between the posts because it's the only information which all posts can have in common and is related to the actual topic of the post. Therefore i needed data of all posts overall and data about the current posts. The data from the current post will be just passed as props to the component. All post data for my website is created in a CMS which can be accessed via GraphQL. The query to get allPosts looks like this.

js
Copy code
export async function getAllPosts() {
  const data = await fetchStrapiAPI(
    `
    {
      posts(sort: "published_at:desc") {
        id
        published_at
        title
        slug
        content
        excerpt
        tags {
          name
        }
        coverImage {
          url
        }
      }
    }
  `
  )
  return data?.posts
}

The only relevant information here is the slug and the tags with their names.

Now the current post gets filtered out from the posts array and a variable maxPosts for the maximum number of posts which should be displayed will be created.

js
Copy code
// filter out current post
let posts = allPosts.filter((aPost) => aPost.slug !==post.slug);
    
// define maxPosts to display
const maxPosts = 3

For better readability I assigned the tasks of the current posts to a variable called currentTags

js
Copy code
// get tags of current posts
const currentTags = post.tags.map((tag) => {
  return tag.name
})

Now you have to map through posts and the tags post.tags of these posts to check if one of these tags is the same as one of the currentTags. If one tag is the same we will just enumerate a new relevance variable.

js
Copy code
// rate posts depending on tags
    posts.forEach((post) => {
        post.relevance = 0
        post.tags.forEach((tag) => {
            if (currentTags.includes(tag.name)) {
                post.relevance ++
            }
        })
    })

The post with the highest relevance will be the post with the most common tags and be the most related post. If you are also using categories you can of course also adjust the relevance depending on the categories and the tags. For example you could add two relevance points for categories and one relevance point for tags.

Then you can sort the array of all posts descending by relevance.

js
Copy code
// sort posts by relevance
    const sortedPosts = posts.sort(function(a, b) {
        return b.relevance - a.relevance;
    });

In the end you can slice them with maxPosts and finally render them.

js
Copy code
import PostPreview from 'src/components/article/article-preview/article-preview'

export default function RecommendedPosts({ post, allPosts }) {

    // filter out current post
    let posts = allPosts.filter((aPost) => aPost.slug !==post.slug);
    
    // define maxPosts to display
    const maxPosts = 3

    // get tags of current posts
    const tags = post.tags.map((tag) => {
        return tag.name
    })

    // rate posts depending on tags
    posts.forEach((post) => {
        post.relevance = 0
        post.tags.forEach((tag) => {
            if (tags.includes(tag.name)) {
                post.relevance ++
            }
        })
    })

    // sort posts by relevance
    const sortedPosts = posts.sort(function(a, b) {
        return b.relevance - a.relevance;
    });

    return (
        <>
          {sortedPosts.slice(0,maxPosts).map((post, i) => (
            <PostPreview
              key={i} 
              postData={post}
            />
          ))}
        </>
    )
  }

Table of contents

First published September 23, 2022

    0 Webmentions

    Have you published a response to this? Send me a webmention by letting me know the URL.

    Found no Webmentions yet. Be the first!

    Write a comment

    About The Author

    Max
    Max

    Geospatial Developer

    Hi, I'm Max (he/him). I am a geospatial developer, author and cyclist from Rosenheim, Germany. Support me

    0 Virtual Thanks Sent.

    Continue Reading

    1. Building a Table of Contents (TOC) from markdown for your React blog

      How to create a Table of Contents (TOC) from markdown for your React blog with Javascript without any third party dependencies.

      Continue reading...

    2. How to create a custom cookie banner for your React application

      Recently I implemented a custom cookie banner solution on my Next.js site which you probably have seen a few seconds before. There are a lot of prebuilt cookie banners you can use for React or Next js sites but i wanted to create a custom cookie banner which also has some personal touch and keeps the design with the website in line.

      Continue reading...

    3. Using Google Adsense with GatsbyJS

      In general there are two possibilies to use Google Adsense on your GatsbyJS website Auto Ads and custom display blocks.Depending on whether you choose to include Adsense ads on certain spots or whether you will leave this job to the Google AI, you can choose one/and or the other.

      Continue reading...