Gatsbyブログの記事をタグ(カテゴリ)管理する:その②タグ一覧ページを作る

2022/4/18

(最終更新: 2022/4/18

はじめに

今回やること

Gatsby.jsで作成中のブログに、内容を表すタグ(カテゴリ)を設定できるようにします。 ※タグとカテゴリは、厳密には意味が異なるようなのでここではタグに統一します。

タグ一覧ページを作成します。

タグ一覧ページ

また、

  • ナビゲーションバーからタグごとの記事ページにリンク追加

も実施します。

※前回の記事では、タグごとに「そのタグがついている記事一覧」を表示できるようにしました。

参考資料

https://bunsugi.com/gatsby-blog-article-list-groupby-tag/

タグの記事一覧ページイメージ

機能の前提

  • 1つの記事に対し、複数のタグをつけることを可能とします。
  • タグは記事内のfrontmatterで配列として設定することにします。
  • タグは日本語も可能としますが、「そのタグがついている記事一覧」のURLは半角英数字とします。
  • 「そのタグがついている記事一覧」のURLは、タグの内容と1:1で紐づけ、JSONで管理します。
  • タグ自体の一覧を表示できるようにします。

タグ一覧ページを作成する

今回は、自動でページを作成する必要はありません。

固定ページとしてタグ一覧ページを作成します。

src/pages/tags.js
import React from "react"
import _ from "lodash"
import { useStaticQuery, graphql } from "gatsby"
import Layout from "../components/layout"
import Seo from "../components/seo"
import { ListItem, UnorderedList } from "@chakra-ui/react"
import { Link } from "gatsby"
import Search from "../components/organisms/search"
import Profile from "../components/organisms/profile"
import MainHeaderBar from "../components/atom/main-header-bar"
import { AllTagDefinition } from "../params/all-tag-difinition"
import { Helmet } from "react-helmet"

const Tags = ({ location }) => {

  const data = useStaticQuery(
    graphql`
      {
        site {
          siteMetadata {
            title
          }
        }
        tagsGroup: allMdx {
          group(field: frontmatter___tags) {
            fieldValue
            totalCount
          }
        }
      }
    `
  )

  const siteTitle = data.site.siteMetadata?.title || `Title`


  const tags = data.tagsGroup.group

  return (
    <Layout
      location={location}
      title={siteTitle}
    >
      <Seo title="タグ一覧"></Seo>
      <Helmet>
        <meta name="robots" content="noindex" />
      </Helmet>
      <MainHeaderBar as="h1">タグ一覧</MainHeaderBar>
      <UnorderedList listStyleType="none">
        {tags.map((tag) => {
          // タグの英名を取得する(gatsby-node.jsと同じ処理である必要があります)
          const tagDefinition = AllTagDefinition.filter(
            (item) => item.name === tag.fieldValue
          )
          const tagSlug =
            tagDefinition.length === 0 ? tag.fieldValue : tagDefinition[0].slug // 定義に無かった場合(filterした結果が空配列)は日本語のままslugにする。

          return (
            <Link to={`/tags/${_.kebabCase(tagSlug)}`}>
              <ListItem
                p={1}
                borderBottom="1px"
                borderColor="orange.100"
                mb={1}
              >{`${tag.fieldValue} (${tag.totalCount})`}</ListItem>
            </Link>
          )
        })}
      </UnorderedList>
    </Layout>
  )
}

export default Tags

GraphQLでタグ一覧を取得する

前回の記事と同じようにタグ一覧を取得します。

固定ページなので、ページクエリではなくuseStaticQueryを利用可能です。

import { useStaticQuery, graphql } from "gatsby"
  const data = useStaticQuery(
    graphql`
      {
        site {
          siteMetadata {
            title
          }
        }
        tagsGroup: allMdx {
          group(field: frontmatter___tags) {
            fieldValue
            totalCount
          }
        }
      }
    `
  )

  const tags = data.tagsGroup.group

noindex設定をする

諸説あると思いますが、タグ一覧ページはGoogleにインデックスされても仕方ないのでnoindex設定をしておきます。

import { Helmet } from "react-helmet"
<Helmet>
<meta name="robots" content="noindex" />
</Helmet>

タグ一覧をリスト表示する

タグ一覧をリスト表示します。

<Link>の先には、タグごとの記事一覧ページへのリンクを貼ります。

このURL(tagSlug)導出ロジックは前回と同じにしておく必要があります。

import { Link } from "gatsby"
import { AllTagDefinition } from "../params/all-tag-difinition"
{tags.map((tag) => {
    // タグの英名を取得する(gatsby-node.jsと同じ処理である必要があります)
    const tagDefinition = AllTagDefinition.filter(
    (item) => item.name === tag.fieldValue
    )
    const tagSlug =
    tagDefinition.length === 0 ? tag.fieldValue : tagDefinition[0].slug // 定義に無かった場合(filterした結果が空配列)は日本語のままslugにする。

    return (
    <Link to={`/tags/${_.kebabCase(tagSlug)}`}>
        <ListItem
        >{`${tag.fieldValue} (${tag.totalCount})`}</ListItem>
    </Link>
    )
})}

ナビゲーションバーからタグごとの記事ページにリンク追加

ナビゲーションバーは以下のようなコンポーネントで定義しています。

※長くなるので見た目の装飾部分は省略します。

src/components/organisms/nav.js
import * as React from "react"
import { Link } from "gatsby"
import { Box, HStack, Text } from "@chakra-ui/react"
import NavBarTags from "../../params/nav-bar-tags"

const Nav = () => {

  const navItem = [
    ...NavBarTags,
    { name: "このブログについて", slug: "about" },
  ]

  return (
    <Box>
      <Box maxW="1201px" mx="auto">
        {/* ↑幅は、layout.jsの外側のフレームの大きさと合わせている。 */}
        <HStack>
          {navItem.map((item, index) => (
            <Link to={`/${item.slug}`}>
              <Box>
                <Text>
                  {item.name}
                </Text>
              </Box>
            </Link>
          ))}
        </HStack>
      </Box>
    </Box>
  )
}

export default Nav

ナビゲーションバーに設定する値の設定

まず、navItemで、ナビゲーションバーに表示するアイテムの 名前リンク先URL を設定します。

import NavBarTags from "../../params/nav-bar-tags"
  const navItem = [
    { name: "Home", slug: "" },
    ...NavBarTags,
    { name: "このブログについて", slug: "about" },
  ]

ここで、NavBarTagsは別ファイルで管理しています。

注意点として2点あります。

  • all-tag-difinitionで管理している、タグに対する記事一覧ページのURL設定と合わせる必要があります。
  • ただし、slugtags/slugとする必要があります。たとえば「プログラミング」のslugは、all-tag-difinitionでは
  {
    name: "プログラミング",
    slug: "programming",
  },

と設定しましたが、nav-bar-tagsでは

  {
    name: "プログラミング",
    slug: "tags/programming",
  },

とする必要があります。

単純に、<Link to=>に設定するURLを記事一覧ページと合わせる都合でこのようになってしまいました。

src/params/nav-bar-tags.js
// 必ずall-tag-difinition.jsから抜粋すること。
// さらに、slugには `tags/`を追加すること。
const NavBarTags = [
  {
    name: "プログラミング",
    slug: "tags/programming",
  },
  {
    name: "息抜き",
    slug: "tags/break-life",
  },
]

export default NavBarTags

map関数でリストを描画する

取得したnavItemを横に並べていきます。

ここで<Link to=>の中身は{`/${item.slug}`}とします。

item.slugの前に/を入れているのがポイントです。

{navItem.map((item, index) => (
<Link to={`/${item.slug}`}>
    <Box>
    <Text>
        {item.name}
    </Text>
    </Box>
</Link>
))}      

## ハマったポイント

各リンクのリンク先URLは注意が必要です。

<Link>コンポーネントは、/があるか、無いかで絶対パスか相対パスかが決まります。

例えば<Link to="tags">とした場合は、今いるページに対してtagsを追加したURLに飛んでしまいます。

相対パスと絶対パス

そのため/を忘れると、ナビゲーションバーをクリックしたページによって行き先が変わってしまうことになります。

ナビゲーションバーのリンク先は以下。 ナビゲーションバーのリンク先

タグ一覧ページのリンク先は以下。 タグ一覧ページのリンク先

タグ一覧ページをサイドバーにも置きました。 サイドバーのリンク先

このように設定できるよう、各ページのリンク先URLを設定しました。

まとめ

Gatsby.jsのブログに対し、タグを設定し、タグ一覧ページを作成することができました。



個別連絡はこちらへ→Twitterお問い合わせ

プロフィール

プロフィールイメージ

はち子

事業会社のシステム部門に異動して4年目の会社員。システム企画/要件定義/システムアーキテクチャ等。

Twitter→@bun_sugi

過去の記事について

はてなブログに掲載の記事(主にプログラミングメモ)についてはこちらに掲載しております。(本ブログに移行中)

タグ一覧

関連記事

Copyright© 2022, エンジニアを目指す日常ブログ

お問い合わせ|プライバシーポリシー