これは Craft CMS Advent Calendar 2020 7日目の記事です。
詳細ページを作ったのでタグアーカイブを作成してみる。
タグのリストを表示する
トップページにタグのリストを表示して、 tags/{slug}
にリンクされるようにしてみる。
src/pages/index.js
import React from "react" import { useStaticQuery, graphql } from "gatsby" import { Link } from "gatsby" const RecentEntriesQuery = graphql` { allCraftTestTestEntry(limit: 10) { nodes { id title url slug ... on Craft_test_test_Entry{ testredactor testtags{ id title } } } } allCraftTags1Tag { tagList: nodes { id title } } } `; export default function Home() { const {allCraftTestTestEntry: {nodes}, allCraftTags1Tag:{tagList}} = useStaticQuery(RecentEntriesQuery); return ( <div> <h1>Hello world!</h1> <div className="flex flex-wrap -mx-4"> {nodes.map(({id, title,url,slug}) => ( <p><Link to={`/article/${slug}`}>{title}</Link></p> ))} </div> <h2>タグリスト</h2> <ul className="flex flex-wrap -mx-4"> {tagList.map(({id, title}) => ( <li><Link to={`/tags/${title}`}>{title}</Link></li> ))} </ul> </div> ) }
タグの一覧を取得する allCraftTags1Tag
を追加する。
all は一覧をとるということで
Craft は決まり事みたいなもんで
Tags1 はタググループのハンドル
Tag はタグを取得するという意味になる
Fetching Craft Content : Gatsby source plugin for Craft CMS
https://github.com/craftcms/ga...
タグの一覧が無事取得できた。
タグアーカイブページを出力する
リンク先のタグアーカイブページを作成していく。gatsby-node.js を編集する。
gatsby-node.js
const path = require('path'); exports.createPages = ({ graphql, actions }) => { const {createPage} = actions return graphql(` { allCraftTestTestEntry(limit: 10) { nodes { id title url slug ... on Craft_test_test_Entry{ testredactor testtags{ id title } } } } allCraftTags1Tag { tagList: nodes { id title } } } `).then(result => { const allEntries = result.data.allCraftTestTestEntry.nodes allEntries.forEach(node => { createPage({ path: `article/${node.slug}`, component: path.resolve(`./src/templates/post.js`), context: { pagedata: node }, }) }) const tagArchive = result.data.allCraftTags1Tag.tagList tagArchive.forEach( tag => { createPage({ path: `tags/${tag.title}`, component: path.resolve(`./src/templates/tagarchive.js`), context: { tagdata: tag, tagId: tag.id, allEntries: allEntries }, }) }) }) }
にも同じように
allCraftTags1Tag { tagList: nodes { id title } }
を追加しておく。
受け取ったレスポンスを使ってタグアーカイブページを生成する。
const tagArchive = result.data.allCraftTags1Tag.tagList tagArchive.forEach( tag => { createPage({ path: `tags/${tag.title}`, component: path.resolve(`./src/templates/tagarchive.js`), context: { tagdata: tag, tagId: tag.id, allEntries: allEntries }, }) })
タグアーカイブページの中身のエントリも allEntries
で渡しておいてそこからフィルタかけた方がいいのかな、、、という気がしつつ、スキル不足でそこは出来なかったので後日の課題。
毎回全てのエントリがきっかけになると無駄そうな気もするが。
ビルドする時間とかはこの辺をちゃんと見ておこう。
- Conditional Page Builds | Gatsby
https://www.gatsbyjs.com/docs/... - Incremental Builds – Gatsby Cloud
https://support.gatsbyjs.com/h... - A guide to Gatsby incremental builds - LogRocket Blog
https://blog.logrocket.com/gat...
タグアーカイブ内の記事リストの表示
タグアーカイブの中を作成していく。
src/templates/tagarchive.js
import React from "react" import {Link} from "gatsby"; const TagArchive = ({ pageContext, data:{tagarchive: {nodes}} }) => { const { tagdata, allEntries } = pageContext return( <div> <h1>タグ「{tagdata.title}」の記事一覧:{tagdata.id}</h1> <h2>タグがついた一覧</h2> {nodes.map(({id,slug,title,testtags}) => ( <p><Link to={`/article/${slug}`}>{title}</Link>:: タグ {testtags.map((tag) => ( <div>title: {tag.title} / {tag.id}</div> ))}</p> ))} </div> ) } export default TagArchive export const query = graphql` query ($tagId : String){ tagarchive: allCraftTestTestEntry(limit: 10, filter: {testtags: {elemMatch: {id: {eq: $tagId}}}}) { nodes { id title url ... on Craft_test_test_Entry { testredactor testtags { id title } } } } } `;
渡ってきた pageContext
を受け取っておきつつ、このページで取得した tagarchive
のクエリの内容を使って一覧を出力する。
この部分がページ生成と一緒にやったらいいんじゃないか、という気がするが。。。
このあたり色々理解が出来ていない。
gatsby-node.js
で tagId: tag.id,
を渡しておいて、このタグアーカイブのページでそれをそのまま利用する。
Gatsby Helper
の方なのか gatsby-source-craft
の話なのかはわからないが。tag
の id
としてかえってくるのが tags1_Tag:200:1
こういうのだった。tags1
はタググループのハンドルだと思うし、 _Tag
はタグってことで、 200
がID。
:1
はよくわからん・・・
この辺はプラグイン周りがアップデートあると変わりそうなきはする。
id
としてうけとってそのまま渡せば問題ないのでひとまずは問題なし。
タグでフィルタをかけて取得するところは
export const query = graphql` query ($tagId : String){ tagarchive: allCraftTestTestEntry(limit: 10, filter: {testtags: {elemMatch: {id: {eq: $tagId}}}}) { nodes { id title url ... on Craft_test_test_Entry { testredactor testtags { id title } } } } } `;
こんなかんじで
allCraftTestTestEntry(limit: 10, filter: {testtags: {elemMatch: {id: {eq: $tagId}}}}
elemMatch
でフィルタをかけてやると問題なくとれた。
ちなみに Craft CMS 上の GraphiQLでやるときはこんな感じなので
{ tags(group: "tags1", id: "200") { id title } }
取り方も違うので気をつける。
$tagId
は ID
で宣言しておかないといけないかと思ったが String
でよかったらしい。
tagarchive
で受け取った結果をループしてページを表示する。
最初にも書いたけど、gatsby-node.js
での Query
を元にタグアーカイブは作れないものかはまた今度試してみよう。