Gatsby + Airtableサイトにカテゴリを追加した(2)
2018年12月30日
パート1の続きです。Gatsby + Airtable + Netlifyで作っているこのサイトにカテゴリを追加した時の手順の記録です。
パート1では以下の1を書いたので、パート2では2と3を記録しておきます。
- 記事ページでカテゴリ表示を追加
- 各カテゴリの記事一覧ページを追加
- カテゴリ一覧ページを追加
2. 各カテゴリの記事一覧ページを追加
各カテゴリの記事一覧ページを追加しました。記事ページと同じ要領で、テンプレートを作ってgatsby-node.js
のcreatePage
でページを生成しました。
テンプレートページの作成
以下にソースコードを晒しちゃいます。
import React from "react"
import { graphql, Link } from "gatsby"
import Layout from "../components/layout"
import styles from "./blog-post.module.scss"
import indexStyles from "../pages/index.module.scss"
import Meta from "../components/meta"
class categoryTemplate extends React.Component {
render(){
const cat = this.props.data.category
const posts = this.props.data.posts
const postCount = posts.edges.length
return (
<Layout location="category" backLink={true}>
<Meta
page="category"
title={`「${cat.data.catname}」関連のノート`}
description={`「${cat.data.catname}」関連のノート`}
slug={cat.data.slug}
/>
<h1 className={styles.postTitle}>{`Note${postCount > 1 ? `s` : ``} on ${cat.data.catname}`}</h1>
<ul className={indexStyles.postlist}>
{posts.edges.map(({ node }, index) => (
<li key={index}>
<span>{node.data.date}</span><br />
<Link
to={`${node.data.slug}/`}
>{node.data.title}
</Link>
</li>
))}
</ul>
</Layout>
)
}
}
export default categoryTemplate
export const query = graphql`
query($slug: String!){
category: airtable(data: {slug: {eq: $slug}}) {
data {
catname
slug
}
}
posts: allAirtable(
filter: {
table: {eq: "entry"},
data: {category: {elemMatch: {data: {slug: {eq: $slug}}}}}
},
sort: {fields: [data___date], order: DESC}
) {
edges {
node {
data {
title
slug
date(formatString: "YYYY/MM/DD @HH:mm")
}
}
}
}
}
`
gatsby-node.jsの変更
カテゴリの記事一覧ページ用のコードを追加しました。loadPages
で記事を、loadCategories
でカテゴリの記事一覧ページを生成しています。
exports.createPages = ({ graphql, actions}) => {
const { createPage } = actions
const loadPages = new Promise((resolve, reject) => {
graphql(`
{
allAirtable(
filter: { table: {eq: "entry"} },
) {
edges {
node {
data {
slug
}
}
}
}
}
`
).then(result => {
result.data.allAirtable.edges.forEach(({ node }) => {
createPage({
path: node.data.slug,
component: path.resolve(`./src/templates/blog-post.js`),
context: {
slug: node.data.slug,
},
})
})
resolve()
})
})
const loadCategories = new Promise((resolve, reject) => {
graphql(`
{
allAirtable(
filter: {
table: {eq: "category"},
data: {entry: {ne: null}},
},
sort: {fields: [data___slug], order: ASC}
) {
edges {
node {
data {
slug
}
}
}
}
}
`).then(result => {
result.data.allAirtable.edges.forEach(({ node }) => {
createPage({
path: `/category/${node.data.slug}`,
component: path.resolve(`./src/templates/category.js`),
context: {
slug: node.data.slug,
},
})
})
resolve()
})
})
return Promise.all([loadPages, loadCategories])
}
3. カテゴリ一覧ページを追加
カテゴリ一覧ページは、Airtableから取得したデータを書き出すだけなので簡単にできました。GraphQLのクエリにfilter
にdata: {entry: {ne: null}}
を追加して記事に使われていないカテゴリを表示しないようにしました。
import React from "react"
import { graphql, Link } from "gatsby"
import Layout from "../components/layout"
import Meta from "../components/meta"
import postStyles from "../templates/blog-post.module.scss"
import styles from "./category.module.scss"
class catListTemplate extends React.Component {
render() {
const cats = this.props.data
return (
<Layout backLink={false}>
<Meta
page="category"
title="カテゴリ一覧"
description="R noteのカテゴリ一覧"
slug="categories"
/>
<h1 className={postStyles.postTitle}>カテゴリ一覧</h1>
<ul className={styles.catList}>
{cats.allAirtable.edges.map(({ node }, index) => (
<li key={index}>
<Link
to={`category/${node.data.slug}/`}
>{node.data.catname}
</Link>
</li>
))}
</ul>
</Layout>
)
}
}
export default catListTemplate
export const query = graphql`
query{
allAirtable(
filter: {
table: {eq: "category"},
data: {entry: {ne: null}}
},
sort: {fields: data___slug, order: ASC}
) {
edges {
node {
data {
catname
slug
}
}
}
}
}
`
以上です!