はじめに

中野区在住の中野です。

Gatsby.jsで関連記事機能を作ったのですがハマったのでメモを残しておきます。

Gatsby.jsに関連記事機能を実装する中でハマった話

  • 関連記事機能とは
  • ボツ案
  • 実際の実装
  • 今回のハマりポイントと反省

関連記事機能とは

簡単に言えばベースとなる記事についたtagがついている記事を集めてきてリンクを作って表示する機能です。

ボツ案

StaticQueryの中に今の記事に紐づく tags を渡して該当のtagを含む記事一覧を取得するQueryを書きました。

しかし、Staticということもあり、外部からパラメータを渡すことができなかったのでこちらの案はボツになりました。

これができるのであればQuery書いてmapするだけで実装は終了でした。

以下がイメージしていたQueryです

query RelatedArticles($tags: [String!]) {
allMdx(filter: {frontmatter: {tags: {in: $tags}}}, sort: {order: DESC, fields: [frontmatter___date]}) {
edges {
node {
id
slug
frontmatter {
tags
category
title
}
}
}
}
}

実際の実装

一旦全ての記事を取得するQueryを実行し、今の記事に紐づく tags を条件にfilterしていきます。

実際に書いたコードは以下です

import React from "react"
import { Link, useStaticQuery, graphql } from "gatsby"
const RelatedArticleList = ({ post }) => {
const { allMdx } = useStaticQuery(
graphql`
query{
allMdx {
nodes {
id
slug
frontmatter {
category
tags
title
}
}
}
}
`
);
return (
<nav>
<h1>関連記事</h1>
<ul>
{
allMdx.nodes.map(node => {
const relatedArticle = filter(node, post)
if (relatedArticle.length) {
return(getLink(relatedArticle))
}
})
}
</ul>
</nav>
);
};
function filter(node, post) {
const relatedArticle = [];
for(let i = 0; i < post.tags.length; i++) {
// 一致するタグを含んでいる && relatedArticleが空 && 同じ記事ではない
if (node.frontmatter.tags?.includes(post.tags[i]) && !relatedArticle.length && !(`/${ node.slug }` === post.slug)) {
relatedArticle.push(node)
}
}
return(relatedArticle)
}
function getLink(relatedArticle) {
return(
relatedArticle.map(node=>{
return(
<li key={ node.id }>
<Link to={ `/${ node.slug }` }>
{ node.frontmatter.title }
</Link>
</li>
)
})
)
}
export default RelatedArticleList

今回のハマりポイントと反省

  • gatsby-theme-blog のQueryでデフォルトで登録されてた frontmatterkeytag ではなく tags でした。
    • 過去のコードから記事まで全部renameしました。コアのものこそ先に確認するべきでした。
  • staticQuery は考えてみれば当然ですが、可変な挙動ができない。
    • 「名は体を表す」というのに全然気づかずに実装してました。
  • gatsby-node.js 内の createPages で、returnに複数のページ作成のQueryを渡すことができる。
    • ページ作成ごとにreturnしていると最後にreturnしたものしか表示されてないことに気づき修正しました。
    • こちらも「名は体を表す」というのに全然気づかずに実装してました。

さいごに

今までの機能はQuery書いてmapするだけだったのでjsを書くという実感はなくQueryを書くだけでした。

今回は取得してきたデータを加工することを書く必要があったのでコード書いてる感がありました。

おかげで今まで以上にjsと仲良くなれた気がします。

\ Share /

全人類同時接続数No.1!バトルロイヤルゲームを生き残れ!

中野区在住の中野です。大阪生まれ大阪育ちですが就職のタイミングで上京しました。食いっぱぐれないようにすることをモットーに生存戦略を常に考えている元ネトゲ廃人現フルリモートwebエンジニア。Twitterでメンターとして駆け出しエンジニアたちをサポートしています。最近の関心事はDDDとScrum。いずれ起業することを考えてプロダクトを作成中。このブログでは生存戦略を考える上で試行錯誤した内容を記録していきます。