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 レンダリングされるページを管理するために使用する小道具。

gatsby-node.js
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')
  });
};

レンプレート

The gatsby-awesome-pagination プラグインは、私が知る限り、個別の「アーカイブ」ページをページ付けするためのものです。 したがって、スターターのホームページにページネーションを追加する代わりに、すべてを含む別の投稿ページにリンクします。 通常のページの投稿のグループは、静的なクエリと、表示内容を管理するためのカルーセルのようなものを使用するのがおそらく最適です。

index.js
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 に値を渡します skiplimit 引数も設定する必要があります。

blog-archive.js
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 あなたは見ることができます skiplimit クエリに渡されるプロパティと pageNumbernumberOfPages これを使用して、各ページの番号とリンクを生成できます。

components / pager.js
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;

投稿

各投稿間にナビゲーションを追加するのも同じくらい簡単で、プラグインも必要ありません。 この特定のスターターは実際にはすでにこれをサポートしていますが、今のところサポートしていないふりをしましょう。

クエリからページを作成する場合は、2つのフィールドを追加するだけで、これらのフィールドにアクセスできます。 pageContext. それが最初の投稿である場合は prev 存在しないはずです。存在しない場合は、最後の投稿を返します。 と同じ next、次の投稿が存在する場合にのみ返します。

gatsby-node.js
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、これで完了です。

blog-post.js
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;

まとめ

このプラグインはまだ解決されていませんが、このすでに信じられないほどシンプルなデザインがどのように改善されるかを楽しみにしています。