gatsby-prevnext

GatsbyJSで作ったブログに「次の記事」「前の記事」のリンクを実装する方法

2022-02-21

はじめに

勉強しながら少しずつブログに機能を追加してますが、今回は「次の記事」「前の記事」のリンクを実装していきたいと思います。

gatsby-node.jsでデータを取得してデータを渡す

先ずはgatsby-node.jsで「次の記事」「前の記事」のデータを取得できるようにします。GraphQlでnextとpreviousを取得します。取得できるデータはhttp://localhost:8000/___graphqlで確認してみてください。

gatsby-node.js
await graphql(`
    {
      allMarkdownRemark(
        sort: { order: DESC, fields: [frontmatter___date] }
        ){        
          next {
            fields {
              slug
            }
            frontmatter {
              title
              date
              featuredimage {
                childImageSharp {
                  gatsbyImageData (
                  )
                }
              }
            }
          }
          previous {
            fields {
              slug
            }
            frontmatter {
              title
              date
              featuredimage {
                childImageSharp {
                  gatsbyImageData (
                  )
                }
              }
            }
          }
        }
      }
    }

次にallMarkdownRemarkで取得したデータを各テンプレートsrc/templates/${String(edge.node.frontmatter.templateKey)}に渡します。

gatsby-node.js
const posts = result.data.allMarkdownRemark.edges

posts.forEach((edge) => {
 const id = edge.node.id
 createPage({
  path: edge.node.fields.slug,
  tags: edge.node.frontmatter.tags,
  component: path.resolve(
   `src/templates/${String(edge.node.frontmatter.templateKey)}.js`
  ),
  context: {
   id,
   next: edge.next, //追加
   previous: edge.previous, //追加
  },

templateデータを受け取る

データを渡したらデータを受け取りましょう。ブログ記事に「次の記事」「前の記事」を実装したいので、受け取る場所はブログテンプレートです。propsでpageContextが使えるようになり、contextのデータを受け取ることができます。受け取ったらPrevNextコンポーネントを作っているのでさらにデータを渡します。

/src/templates/blog-post.js
export const BlogPostTemplate = ({
    //...省略
  pageContext,
}) => {
  return (
            //...省略
       <PrevNext pageContext={pageContext} />
  );
};

 //...省略

const BlogPost = ({ data, pageContext}) => {
  const { markdownRemark: post } = data;
  const { siteUrl } = useSiteMetadata();
  return (
    <Layout>
      <BlogPostTemplate
	       //...省略
        pageContext={pageContext}
      />
    </Layout>
  );
};

PrevNextコンポーネントはこんな感じです。スタイリングはここで加えていきます。

/src/components/prevNext.js
import React from "react"
import { Link } from 'gatsby'
import PreviewCompatibleImage from './PreviewCompatibleImage'

const prevNext = ({ pageContext }) => {
  const { next, previous } = pageContext;
      return (
        <div className="columns blog-module--prev-next">
          { previous.frontmatter.date == null || previous == null ? null :              
               <div className="column is-half">                 
                <h3>次の記事</h3>
                 <div className="line-height-initial">
                  <Link to={`${previous.fields.slug}`} className="MuiButtonBase-root">
                    {previous.frontmatter.featuredimage ? (
                      <div className="MuiBox-root">
                        <PreviewCompatibleImage
                          imageInfo={{
                            image: previous.frontmatter.featuredimage,
                            alt: `featured image thumbnail for post ${previous.frontmatter.title}`,
                          }}
                        />
                      </div>
                    ) : null}
                    <div className="MuiCardContent-root">
                    <span className="is-size-small-2">
                    {previous.frontmatter.title}
                    </span>
                   </div>
                  </Link>
                 </div>
               </div>
              }
          {  next ==  null ? null :
             <div className="column is-half">
                <h3>前の記事</h3>
                <div className="line-height-initial">
                 <Link to={`${next.fields.slug}`} className="MuiButtonBase-root">
                  {next.frontmatter.featuredimage ? (
                    <div className="MuiBox-root">
                      <PreviewCompatibleImage
                        imageInfo={{
                          image: next.frontmatter.featuredimage,
                          alt: `featured image thumbnail for post ${next.frontmatter.title}`,
                        }}
                      />
                    </div>
                  ) : null}
                  <div className="MuiCardContent-root">
                  <span className="is-size-small-2">
                  {next.frontmatter.title}
                  </span>
                 </div>
                </Link>
             </div>
            </div>
            } 
        </div>
        )
 }

 export default prevNext;

スタイリングなど少し雑ですがこれで実装完了です。gatsby-node.jsのデータの渡し方の仕組みなど理解することができて学びが多い実装になりました。参考になれば幸いです。

© 2022 shintakoji All Rights Reserved