投稿にタグを追加する。タグ一覧ページとタグページを追加する。
目次
投稿のMarkdownへタグを追加する
---
title: Gatsbyにタグを追加する
date: "2023-03-26"
tags: ["gatsby", "plugin", "test"]
---
GraphQLで投稿のタグを取得する
Gatsby起動後にGraphQLのURLにアクセスしてタグデータを取得する。
http://localhost:8000/___graphql
Qrery
投稿をtags
でグループ化し、タグがついた投稿の数をtotalCount
で取得する。
{
allMarkdownRemark {
group(field: { frontmatter: { tags: SELECT } }) {
tag: fieldValue
totalCount
}
}
}
Result
タグと投稿の数が取得できます。
{
"data": {
"allMarkdownRemark": {
"group": [
{
"tag": "gatsby",
"totalCount": 1
},
{
"tag": "plugin",
"totalCount": 1
},
{
"tag": "test",
"totalCount": 1
}
]
}
},
"extensions": {}
}
タグページのテンプレートを作成する(/tags/{tag_name})
選択したタグを含む投稿一覧を表示するテンプレートページを作成する。
ここではテンプレートを作成し、実際のタグごとのページは、後述のgatsby-node.js
のcreatePages
で生成される。
タグページアクセスURLは、localhost:8000/tags/{tag_name}/
。
作成ファイル : src/templates/tags.js
import React from "react"
import PropTypes from "prop-types"
// Components
import { Link, graphql } from "gatsby"
const Tags = ({ pageContext, data }) => {
const { tag } = pageContext
const { edges, totalCount } = data.allMarkdownRemark
const tagHeader = `${totalCount} post${
totalCount === 1 ? "" : "s"
} tagged with "${tag}"`
return (
<div>
<h1>{tagHeader}</h1>
<ul>
{edges.map(({ node }) => {
const { slug } = node.fields
const { title } = node.frontmatter
return (
<li key={slug}>
<Link to={slug}>{title}</Link>
</li>
)
})}
</ul>
{/*
This links to a page that does not yet exist.
You'll come back to it!
*/}
<Link to="/tags">All tags</Link>
</div>
)
}
Tags.propTypes = {
pageContext: PropTypes.shape({
tag: PropTypes.string.isRequired,
}),
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
totalCount: PropTypes.number.isRequired,
edges: PropTypes.arrayOf(
PropTypes.shape({
node: PropTypes.shape({
frontmatter: PropTypes.shape({
title: PropTypes.string.isRequired,
}),
fields: PropTypes.shape({
slug: PropTypes.string.isRequired,
}),
}),
}).isRequired
),
}),
}),
}
export default Tags
export const pageQuery = graphql`
query($tag: String) {
allMarkdownRemark(
limit: 2000
sort: { frontmatter: { date: DESC }}
filter: { frontmatter: { tags: { in: [$tag] } } }
) {
totalCount
edges {
node {
fields {
slug
}
frontmatter {
title
}
}
}
}
}
`
gatsby-node.jsにタグページを生成する記述を追加する
lodash
ライブラリを追加する。
lodash
ライブラリのkebabCase
ファンクションを利用してタグをケバブケースに変更する。
タグ名abc_def
やabcDef
のURLは、/tags/abc-def
になる。
gatsby-node.js
の必要な箇所へタグページを生成する処理を記述する
// ライブラリ読み込み
const _ = require("lodash")
// 以降は、createPagesへ追記
// テンプレートページの読み込み
const tagTemplate = path.resolve("src/templates/tags.js")
// GrapshQLへタグデータ取得処理を追加
tagsGroup: allMarkdownRemark(limit: 2000) {
group(field: { frontmatter: { tags: SELECT }}) {
fieldValue
}
}
// タグテンプレートとタグデータからページを生成する
// Extract tag data from query
const tags = result.data.tagsGroup.group
// Make tag pages
tags.forEach(tag => {
createPage({
path: `/tags/${_.kebabCase(tag.fieldValue)}/`,
component: tagTemplate,
context: {
tag: tag.fieldValue,
},
})
})
タグのインデックス(一覧)ページを作成する
タグのインデックスページを作成する。
アクセスURLは、http://localhost:8000/tags/
。
作成ファイル : src/pages/tags.js
※template/tags.js
とは別のファイル
import React from "react"
import PropTypes from "prop-types"
// Utilities
import kebabCase from "lodash/kebabCase"
// Components
import { Helmet } from "react-helmet"
import { Link, graphql } from "gatsby"
const TagsPage = ({
data: {
allMarkdownRemark: { group },
site: {
siteMetadata: { title },
},
},
}) => (
<div>
<Helmet title={title} />
<div>
<h1>Tags</h1>
<ul>
{group.map(tag => (
<li key={tag.fieldValue}>
<Link to={`/tags/${kebabCase(tag.fieldValue)}/`}>
{tag.fieldValue} ({tag.totalCount})
</Link>
</li>
))}
</ul>
</div>
</div>
)
TagsPage.propTypes = {
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
group: PropTypes.arrayOf(
PropTypes.shape({
fieldValue: PropTypes.string.isRequired,
totalCount: PropTypes.number.isRequired,
}).isRequired
),
}),
site: PropTypes.shape({
siteMetadata: PropTypes.shape({
title: PropTypes.string.isRequired,
}),
}),
}),
}
export default TagsPage
export const pageQuery = graphql`
query {
site {
siteMetadata {
title
}
}
allMarkdownRemark(limit: 2000) {
group(field: frontmatter___tags) {
fieldValue
totalCount
}
}
}
`