web

Next.js × microCMSでページネーションを自作する

公開日:2022年1月11日
最終更新日:2022年1月11日
目次
  • 仕様
  • コード
  • 全体的なロジック

ブログの記事が増えた場合に備えてNext.jsとmicroCMSでページネーションを作りました。

仕様

仕様としては以下です。

  • 「次へ(<)」「前へ(>)」ボタン
  • 1ページ目は「次へ」を非表示、最終ページは「前へ」を非表示
  • 現在ページから±3ページ以上は非表示にし、三点リーダーを表示する
  • 1ページ目と最終ページは常に表示
  • 現在ページはアクティブ状態のスタイルを当てる


コード

必要なデータは全記事数と現在ページの数です。
microCMSでは記事を取得するAPIで totalCount を取得できるので全記事数はこの totalCount を使います。
現在のページ数はパラメータから取得するようにしておきます。

それをPaginationコンポーネントに流し込んでおきます。Paginationのコードは省略してますが、こんな感じです。

export const Pagination = ({
  totalCount,
  currentPage,
  className,
  currentCategory,
}: Props) => {
  const range = (start: number, end: number) =>
    [...Array(end - start + 1)].map((_, i) => start + i)

  // ここはカテゴリでパスを変えてるので、必要な人だけ。
  const paginationPath = currentCategory
    ? `/blog/${currentCategory}/page`
    : `/blog/page`

  // BLOG_PER_PAGEは1ページに表示する件数。
  const lastPage = Math.ceil(totalCount / BLOG_PER_PAGE)

  return (
    <Container className={className}>
      {currentPage !== 1 && (
        <Item>
          <Link href={`${paginationPath}/${currentPage - 1}`} passHref>
            <StyledLink>
              <StyledChevron />
            </StyledLink>
          </Link>
        </Item>
      )}

      <Item key={1}>
        <Link href={`${paginationPath}/${1}`} passHref>
          <StyledLink isCurrent={currentPage === 1}>{1}</StyledLink>
        </Link>
      </Item>
      {range(2, lastPage - 1).map((number, index) => {
        return Math.abs(currentPage - number) < 3 ? (
          <Item key={index}>
            <Link href={`${paginationPath}/${number}`} passHref>
              <StyledLink isCurrent={currentPage === number}>
                {number}
              </StyledLink>
            </Link>
          </Item>
        ) : (
          Math.abs(currentPage - number) === 3 && <Item key={index}>...</Item>
        )
      })}
      <Item key={lastPage}>
        <Link href={`${paginationPath}/${lastPage}`} passHref>
          <StyledLink isCurrent={currentPage === lastPage}>
            {lastPage}
          </StyledLink>
        </Link>
      </Item>

      {currentPage !== lastPage && (
        <Item>
          <Link href={`${paginationPath}/${currentPage + 1}`} passHref>
            <StyledLink>
              <StyledChevron rotate={180} />
            </StyledLink>
          </Link>
        </Item>
      )}
    </Container>
  )
}


全体的なロジック

  • 前へ次へボタン
    • 現在ページが 1 の時は「前へ」を非表示、現在ページが最終ページの時は「次へ」を非表示。
  • 1ページ目と最終ページ
    • この二つは常に表示
  • 2~最終ページ手前まで
    • range をループさせてまずは全部表示する
    • Math.abs(現在ページ - ページ数) から絶対値を出す
    • 絶対値が3の場合は三点リーダー(...)にする
    • 絶対値が4以上の場合は非表示


全体のソースコードはこちらです。

About the author

大阪でフロントエンドエンジニアをしています。写真を撮るのが趣味です。よかったら500pxに載せてる写真も見てください。
web上に公開しているので、正確さに可能な限り努力してますが、個人の備忘録程度に書いてるので、ご自身の判断で参考程度に読んでください。
間違いやご意見があれば、コンタクトやSNSに気軽にご連絡ください。

Read next

Category

  • web
  • 雑記