gatsby-awesome-paginationを使用したGatsbyのページネーション
Gatsbyの驚くべきパフォーマンスにもかかわらず、ユーザーにすべての投稿を同じページにロードするように強制しないのが最善です。 代わりに、 gatsby-awesome-pagination プラグインを調べて、投稿アーカイブをより管理しやすいセクションに分割します。
インストール
マークダウンサポートが付属しているので、gatsby-starter-blogスターターから始めます。
$ gatsby new pagination-example https://github.com/gatsbyjs/gatsby-starter-blog
$ yarn add gatsby-awesome-pagination
ページ付け
gatsby-node.js
ファイルで、paginate
メソッドをインポートし、投稿のクエリの下にオブジェクトを渡します。 必要なのは、createPage
アクション、投稿の配列、ページあたりのアイテム制限、新しいアーカイブページのスラッグ、およびそのテンプレートです。 このクエリを実行すると、レンダリングされるページを管理するために使用するpageContext
プロップにたくさんの追加情報が表示されます。
const { paginate } = require('gatsby-awesome-pagination');
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const blogPost = path.resolve(`./src/templates/blog-post.js`)
const result = await graphql(` ... `)
paginate({
createPage,
items: result.data.allMarkdownRemark.edges,
itemsPerPage: 3,
pathPrefix: '/posts',
component: path.resolve('src/templates/blog-archive.js')
});
};
レンプレート
gatsby-awesome-pagination
プラグインは、私が知る限り、個別の「アーカイブ」ページをページ付けするためのものです。 したがって、スターターのホームページにページ付けを追加する代わりに、すべてを含む別の投稿ページにリンクします。 通常のページの投稿のグループは、静的なクエリと、表示内容を管理するためのカルーセルのようなものを使用するのがおそらく最適です。
import React from "react";
import { Link, graphql } from "gatsby";
import Bio from "../components/bio";
import Layout from "../components/layout";
class BlogIndex extends React.Component {
render() {
const { data } = this.props;
return (
<Layout location={this.props.location}>
<Bio />
<Link to='/posts'><button>See All Posts</button></Link>
</Layout>
)
}
};
export default BlogIndex;
アーカイブテンプレートは、その小道具でクエリのpageContext
にすでにアクセスできます。これは、別のPager
コンポーネントに渡されます。 pageContext
はskip
およびlimit
引数に値を渡すため、静的クエリの代わりに通常のクエリを使用する必要があることに注意してください。セットする。
import Pager from '../components/pager';
export const pageQuery = graphql`
query($skip: Int!, $limit: Int!) {
site { ... }
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: DESC},
skip: $skip,
limit: $limit
) {
edges { ... }
}
}
`;
const BlogArchive = ({ data, pageContext, location }) => {
const posts = data.allMarkdownRemark.edges;
return (
<Layout location={location}>
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<article key={node.fields.slug}>
<header>
<h3>
<Link to={node.fields.slug}> {title} </Link>
</h3>
<small>{node.frontmatter.date}</small>
</header>
<section>
<p dangerouslySetInnerHTML={{ __html: node.frontmatter.description || node.excerpt }} />
</section>
</article>
)
})}
<Pager pageContext={pageContext} />
</Layout>
)
};
export default BlogArchive;
ページャ
最後のステップは、pageContext
からページパスを取得するのと同じくらい簡単です。 pageContext
をログに記録すると、クエリに渡されているskip
およびlimit
プロパティと、pageNumber
およびnumberOfPages
が表示されます。 ]これを使用して、各ページの番号とリンクを生成できます。
import React from 'react';
import { Link } from 'gatsby';
const Pager = ({ pageContext }) => {
console.log(pageContext);
const { previousPagePath, nextPagePath } = pageContext;
return (
<nav style={{ display: 'flex', justifyContent: 'space-between' }}>
<div>
{previousPagePath && (
<Link to={previousPagePath}>
<button>← Newer Posts</button>
</Link>
)}
</div>
<div style={{ justifySelf: 'flex-end' }}>
{nextPagePath && (
<Link to={nextPagePath}>
<button>Older Posts →</button>
</Link>
)}
</div>
</nav>
);
};
export default Pager;
投稿
各投稿間にナビゲーションを追加するのも同じくらい簡単で、プラグインも必要ありません。 この特定のスターターは実際にはすでにこれをサポートしていますが、今のところサポートしていないふりをしましょう。
クエリからページを作成する場合、pageContext
でアクセスできる2つのフィールドを追加する必要があります。 それが最初の投稿である場合、prev
は存在しないはずです。そうでない場合は、最後の投稿を返します。 next
と同じように、次の投稿が存在する場合にのみ返されます。
posts.forEach((post, index) => {
createPage({
path: post.node.fields.slug,
component: blogPost,
context: {
slug: post.node.fields.slug,
prev: index === 0 ? null : posts[index - 1].node,
next: index === (posts.length - 1) ? null : posts[index + 1].node
},
})
});
これは、Pager
の場合と同じ実行であり、prev / nextが存在するかどうかを確認し、Link
にスローすると、完了です。
const BlogPostTemplate = ({ data, pageContext, location }) => {
const post = data.markdownRemark;
const { prev, next } = pageContext;
return (
<Layout location={location}>
<Link to='/posts'>Archive</Link>
<article>
<header>
<h1> {post.frontmatter.title} </h1>
<p> {post.frontmatter.date} </p>
</header>
<section dangerouslySetInnerHTML={{ __html: post.html }} />
<hr />
</article>
<nav style={{ display: 'flex', justifyContent: 'space-between' }}>
<div>
{prev && <Link to={prev.fields.slug} rel="prev"> ← Last Post </Link>}
</div>
<div style={{ justifySelf: 'flex-end' }}>
{next && <Link to={next.fields.slug} rel="next"> Next Post → </Link>}
</div>
</nav>
</Layout>
)
};
export default BlogPostTemplate;
まとめ
このプラグインはまだ解決されていませんが、このすでに信じられないほどシンプルなデザインがどのように改善されるかを楽しみにしています。