GatsbyJSで作ったブログのフッターにタグを追加

公開日: 2020年06月09日最終更新日: 2021年10月17日

タグを記事に表示するようにします。ここでは記事のフッターにその記事につけられているタグを付与します。

まず、タグを表示する部品を追加します。

src\gatsby-theme-blog\components\tag-label.js

import React, { Fragment } from "react"
import { Styled } from "theme-ui"
import { Link } from "gatsby"
import _ from "lodash"

const TagLabel = ({ tags }) => (
    <Fragment style={{ marginTop: 20 }}>
        タグ:
        {tags.map((tag) => (
            <Styled.a style={{ marginLeft: 10 }} as={Link} to={`/tags/${_.kebabCase(tag)}/`}>{tag}</Styled.a>
        ))}
    </Fragment>
)

export default TagLabel

そして記事ページの下部にタグのリストを追加します。

src/gatsby-theme-blog/components/post.js

import React from "react"

import { MDXRenderer } from "gatsby-plugin-mdx"

import Layout from "gatsby-theme-blog/src/components/layout"
import SEO from "gatsby-theme-blog/src/components/seo"
import PostTitle from "gatsby-theme-blog/src/components/post-title"
import PostDate from "gatsby-theme-blog/src/components/post-date"
import PostFooter from "gatsby-theme-blog/src/components/post-footer"
import PostHero from "gatsby-theme-blog/src/components/post-hero"
import _ from "lodash"
import TagLabel from "./tag-label"

const Post = ({
  data: {
    post,
    site: {
      siteMetadata: { title },
    },
  },
  location,
  previous,
  next,
}) => (
  <Layout location={location} title={title}>
    <SEO
      title={post.title}
      description={post.excerpt}
      imageSource={
        post.socialImage
          ? post.socialImage?.childImageSharp?.fluid.src
          : post.image?.childImageSharp?.fluid.src
      }
      keywords={post.keywords}
      imageAlt={post.imageAlt}
    />
    <main>
      <PostHero post={post} />
      <PostTitle>{post.title}</PostTitle>
      <PostDate>{post.date}</PostDate>
      <MDXRenderer>{post.body}</MDXRenderer>
      <TagLabel tags={post.tags} />
    </main>
    <PostFooter {...{ previous, next }} />
  </Layout>
)

export default Post

それとタグの詳細を記事一覧と同じフォーマットに変更します。

src/templates/tag-detail.js

import React from "react"
import PropTypes from "prop-types"
import { Styled } from "theme-ui"
import Layout from "gatsby-theme-blog/src/components/layout"
import SEO from "gatsby-theme-blog/src/components/seo"
import PostLink from "gatsby-theme-blog/src/components/post-link"

// Components
import { Link, graphql } from "gatsby"

const TagDetail = ({ pageContext, data }) => {
    const { tag } = pageContext
    const { edges, totalCount } = data.allMdxBlogPost
    const tagHeader = `${totalCount} post${
        totalCount === 1 ? "" : "s"
        } tagged with "${tag}"`

    return (
        <Layout location={`/tags/${tag}`} title={data.site.siteMetadata.title}>
            <SEO title={`/tags/${tag}`} />
            <Styled.h1>{tagHeader}</Styled.h1>
            <Styled.ul>
                {edges.map(({ node }) => {
                    return (
                        <PostLink key={node.slug} {...node} />
                    )
                })}
            </Styled.ul>
            {/*
              This links to a page that does not yet exist.
              You'll come back to it!
            */}
            <Link to="/tags">
                <Styled.a>
                    All tags
                </Styled.a>
            </Link>
        </Layout>
    )
}

TagDetail.propTypes = {
    pageContext: PropTypes.shape({
        tag: PropTypes.string.isRequired,
    }),
    data: PropTypes.shape({
        allMdxBlogPost: PropTypes.shape({
            totalCount: PropTypes.number.isRequired,
            edges: PropTypes.arrayOf(
                PropTypes.shape({
                    node: PropTypes.shape({
                        title: PropTypes.string.isRequired,
                        slug: PropTypes.string.isRequired,
                    }),
                }).isRequired
            ),
        }),
    }),
}

export default TagDetail

export const pageQuery = graphql`
query ($tag: String) {
    site {
      siteMetadata {
        title
      }
    }
    allMdxBlogPost(limit: 2000, sort: {fields: [date]}, filter: {tags: {in: [$tag]}}) {
      totalCount
      edges {
        node {
          title
          slug
          tags
          date(formatString: "MMMM DD, YYYY")
          excerpt
        }
      }
    }
  } 
`