参考
学習内容
- ブログの詳細ページを作成する
1.前提
slugとは
URL(パーマリンク)の末尾の部分を任意の文字列に指定できる機能で、URLの一部になる
英数字、アンダースコア、ハイフンからなる短いラベル文字列
onCreateNodeとは
Gatsbyで各nodeが生成されるタイミングでnodeにデータを追加し、nodeの再編成をすることができる
- 詳細ページへのslugを生成する
- 作成したslugをnodeに追加する
- gatsby-node.jsに処理を追加する
sample.js
exports.onCreateNode = ({ node, actions }) => {
const { createNode, createNodeField } = actions
// Transform the new node here and create a new node or
// create a new node field.
}
basename関数(Slugの抽出)とは
sample.js
path.basename('/foo/bar/baz/asdf/quux.html', '.html');
// Returns: 'quux'
createNodeFieldとは
sample.js
createNodeField({
node,
name: `happiness`,
value: `is sweet graphql queries`
})
createPages(ページの生成)とは
2.gatsby-node.jsでslugとpageの生成
gatsby-node.js
const path = require('path');
//slugの生成
module.exports.onCreateNode = ({ node, actions }) => {
const { createNodeField } = actions
//MarkdownRemarkの場合に、slugを追加する
if(node.internal.type === 'MarkdownRemark') {
//node.jsのbasename関数を用いてslugを抽出
const slug = path.basename(node.fileAbsolutePath, '.md')
//nodeの再編成 createNodeField: https://www.gatsbyjs.com/docs/reference/config-files/actions/#createNodeField
createNodeField({
node,
name: 'slug',
value: slug
})
}
}
//ページの生成
module.exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
//ブログ詳細ページ用のテンプレートの取得
const blogTemplate = path.resolve('./src/templates/blogDetail.js')
const res = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
//各ページの生成
res.data.allMarkdownRemark.edges.forEach((edge) => {
createPage({
component: blogTemplate,
path: `/blog/${edge.node.fields.slug}`,
context: {
slug: edge.node.fields.slug
}
})
})
}
3.各ページでslugを利用する
index.js
index.js
import React from "react"
import { graphql, useStaticQuery } from "gatsby"
import Layout from "../components/layout"
import Kv from "../components/kv"
import BlogItem from "../components/blogItem"
import {Container, Row, Col} from 'react-bootstrap'
const IndexPage = () => {
//slug追加
const data = useStaticQuery(graphql`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
frontmatter {
date
title
thumbnail {
childImageSharp {
fluid {
src
}
}
}
}
}
}
}
}
`)
return (
<Layout>
<Kv />
<Container>
<Row>
{
data.allMarkdownRemark.edges.map((edge, index) => (
<Col sm={4} key={index}>
<BlogItem
title={edge.node.frontmatter.title}
date={edge.node.frontmatter.date}
src={edge.node.frontmatter.thumbnail.childImageSharp.fluid.src}
//slug追加
link={`blog/${edge.node.fields.slug}`} />
</Col>
))
}
</Row>
</Container>
</Layout>
)
}
export default IndexPage
blogItem.js
blogItem.js
import React from 'react'
import { Card } from 'react-bootstrap'
import { Link } from 'gatsby'
function BlogItem({title, date, src, link}) {
return (
<Card className="mt-4">
<Card.Img variant="" src={src} />
<Card.Body>
<Card.Title>{title}</Card.Title>
<Card.Text>
{date}
</Card.Text>
<Link to={`/${link}`}>see more</Link>
</Card.Body>
</Card>
)
}
export default BlogItem