#5 Gatsby + WordPress REST APIでブログを作ろう【関連記事編】
#4ではパンくずのプラグインを紹介しました
次は記事ページに関連記事を表示させてみましょう
- 同じカテゴリーが1つ以上含まれる関連記事を5つまで表示する
実装するもの
では参ります
gatsby-node.jsの編集
gatsby-node.jsで関連記事を表示するための設定をしていきます
コメントで解説しています
gatsby-node.js
// sortByDateAscending
const sortByDateAscending = (a, b) => {
const aPubDate = (new Date(a.publishedOn)).getTime()
const bPubDate = (new Date(b.publishedOn)).getTime()
if(aPubDate > bPubDate) {
return 1
}
if(aPubDate < bPubDate) {
return -1
}
return 0
}
// Related Posts
const getRelatedPosts = (currentPost, posts) => {
const MINIMUN_CATEGORIES_IN_COMMON = 1 // いくつカテゴリーが共通すれば関連記事として表示するか
// 1つでもカテゴリが共通する
const hasAtLeastOneCategoryInCommon = ({ node }) => {
// 今表示されている記事はfalse
if(currentPost.id === node.id) {
return false
}
// _.intersectionByでカテゴリが共通する記事を取る(今表示されている投稿と、全記事のカテゴリの中で共通のもの全て取る)
const commonCategories = _.intersectionBy(currentPost.categories, node.categories, (categories)=> categories.name)
// 共通カテゴリが1つ以上のものを返す
return commonCategories.length >= MINIMUN_CATEGORIES_IN_COMMON
}
// postsの中から1つでもカテゴリが共通するものをフィルターにかける
const filteredResults = posts.filter(hasAtLeastOneCategoryInCommon)
// 共通カテゴリが5つ以上だったら、Ascendingで並べた配列の0番目から5番目までのみ返す
if(filteredResults.length > 5) {
return filteredResults.sort(sortByDateAscending).slice(0, 5)
}
// 5つ以下の場合はそのままフィルターにかけたものを返す
return filteredResults
}
const BlogPosts = result.data.allWordpressPost.edges
BlogPosts.forEach(post => {
createPage({
path: `/${post.node.slug}`,
component: BlogPostTemplate,
context: {
id: post.node.wordpress_id,
// BlogPostsにデータを渡す
relatedPosts: getRelatedPosts(post.node, result.data.allWordpressPost.edges),
},
})
})
参考動画はこちら
*動画は英語でContentfulを使って実装しているので、そのままやってもうまくいきませんので注意してください
BlogPosts.jsを編集
pageContextで渡ってきたデータを取得できます
BlogPosts.js
import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"
import Layout from "../components/layout"
import SEO from "../components/seo"
import RelatedPosts from "../components/relatedPosts"
const BlogPostTemplate = ({ location, data, pageContext }) => {
const { relatedPosts } = pageContext
return (
<Layout location={location} crumbLabel={data.wordpressPost.title}>
<SEO
title={data.wordpressPost.title}
description={data.wordpressPost.excerpt}
/>
<h1>{data.wordpressPost.title}</h1>
<span>{data.wordpressPost.date}</span>
<span>{data.wordpressPost.categories[0].name}</span>
{data.wordpressPost.featured_media && (
<div>
<Img fluid={data.wordpressPost.featured_media.localFile.childImageSharp.fluid} />
</div>
)}
<div
dangerouslySetInnerHTML={{ __html: data.wordpressPost.content }}
/>
{relatedPosts.length && <RelatedPosts posts={relatedPosts} />}
</Layout>
)
}
export default BlogPostTemplate
export const query = graphql`
query($id: Int!) {
wordpressPost(wordpress_id: { eq: $id }) {
title
content
excerpt
date(formatString: "YYYY.MM.DD")
categories {
name
slug
}
featured_media {
localFile {
childImageSharp {
fluid(maxWidth: 1000) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
`
参考にした動画ではpathContextを使用していますが、非推奨になっているのでpageContextを使いましょう
関連記事が”あれば”RelatedPostsコンポーネントを表示するように条件分岐しています
relatedPosts.jsを作る
components内にrelatedPosts.jsを作りRelatedPostsコンポーネントを作ります
relatedPosts.js
import { Link } from "gatsby"
import React from "react"
import Img from "gatsby-image"
const RelatedPosts = ({ posts }) => (
<div className="yo">
<h2>Related Posts</h2>
<ul>
{posts.map(({node}) =>
<li key={node.id}>
<Link to={`/${node.slug}/`}>
{node.featured_media &&
<Img fluid={node.featured_media.localFile.childImageSharp.fluid} />
}
<span>{node.date}</span>
<span>{node.categories[0].name}</span>
<h4>{node.title}</h4>
</Link>
</li>
)}
</ul>
</div>
)
export default RelatedPosts
単純に渡ってきたpostsを使いmapしているだけなので簡単ですね^ ^
gatsby develop
をしてちゃんと表示されているか確認します
わかりにくいかもですが、ちゃんと表示されています
他のカテゴリに行くと、、、
ちゃんと表示されました^ ^
gatsby-node.jsの設定が難しいかもしれませんが、何度か見直して理解すればオッケーです
ただ、この実装方法の場合、全記事から共通のカテゴリがないか見るのでちょっとコストがかかりすぎていますね
メディアサイトとか記事数がめちゃくちゃある場合は良くないかもしれません。。。
もっと良い実装方法をご存知の方は是非教えてくださいーー!m(_ _)m
では次は「Netlifyにデプロイ」です
お楽しみにーー^ ^
Share if you like
Recent Posts最新記事
- 2022.07.282023.01.01雑記
久しぶりの投稿、何を書いたらいいかわからない
- 2020.05.27写真
最近撮っているiPhoneの写真たち
- 2020.03.26写真
スペイン・バルセロナのトマティーナ祭りツアーの旅の記録【+スナップ写真】
- 2020.03.112020.03.14ライフスタイル
NotionとGoogleカレンダーでタスク管理してみたら便利だった話
- 2020.02.102020.06.13お知らせ
FUJIFILMのグループ展示で写真を出展します
- 2020.01.112020.01.12お知らせ
2019年の振り返りと2020年の抱負
Commentなんでも気軽にどうぞ^ ^