木曜日, 5月 22, 2025
ホームWordPresswordpress + astro.jsのヘッドレスCMS構築の道のり #9 ページネーション2royaltrux

wordpress + astro.jsのヘッドレスCMS構築の道のり #9 ページネーション2royaltrux

🧠 概要:

概要

この記事では、WordPressとAstro.jsを使用したヘッドレスCMSの構築プロセスを紹介しています。特に、ページネーション機能をコンポーネント化する方法に焦点を当てています。このコンポーネント化により、他のカテゴリーや記事ページでも再利用が可能になり、管理が簡単になります。

要約(箇条書き)

  • 目標Pagination.astroコンポーネントを作成し、どのページでも簡単にページネーションを利用できるようにする。
  • ステップ①:共通コンポーネントを新規作成し、totalPagescurrentPagebaseUrlというpropsを受け取る。
  • HTML構造:ページネーションの表示ロジックは論理演算子を使って簡潔に書く。
  • 補足説明
    • 論理演算子(&&)の使用例と三項演算子での条件分岐機能を紹介。
  • ステップ②:スタイルの設定を行い、視覚的な整備を施す。
  • ステップ③
    • タグページやカテゴリページにコンポーネントを組み込み、実際に表示を確認。
    • ビルド後、正しくページネーションが表示されることを確認。
  • 最終確認:異なるタイプのページにコンポーネントを適用することで、再利用の流れを見せる。次回はリダイレクトの設定が予定されている。

この構築方法により、開発者は効率的にページネーション機能を実装し、再利用性を高めることができます。

wordpress + astro.jsのヘッドレスCMS構築の道のり #9 ページネーション2royaltrux

まだまだページネーションの実装が続きます!😅
今回は前回で作ったページネーションを、他のカテゴリーや記事ページでも使えるようにコンポーネント化します!

ページネーションのコンポーネント化のゴール

  • Pagination.astro コンポーネントを作成

  • どのページでも <Pagination totalPages={x} currentPage={y} baseUrl=”/xxx/” /> のように呼び出すだけでOK

  • 見た目や構造は1か所で管理

さてやってみましょう!

ステップ①:共通コンポーネントを作成

ファイルを下記に作ります
src/components/Pagination.astro

まずはスクリプトですが、コンポーネントの中で props を受け取るだけなのでシンプルです😁

--- const { totalPages, currentPage, baseUrl } = Astro.props;---

totalPages、currentPage、baseUrl はコンポーネントを読み込む際に、propsを渡します。

htmlは前回追加したページネーションをそのまま持ってきますが、論理演算子(&&)で分岐させます

{totalPages > 1 && ( <nav class="pagination"> <ul> {currentPage > 1 && ( <li> <a href={`${baseUrl}${currentPage - 1}/`}>← Prev</a> </li> )} {Array.from({ length: totalPages }).map((_, i) => { const pageNum = i + 1; return ( <li> {pageNum === currentPage ? ( <span class="current">{pageNum}</span> ) : ( <a href={`${baseUrl}${pageNum}/`}>{pageNum}</a> )} </li> ); })} {currentPage < totalPages && ( <li> <a href={`${baseUrl}${currentPage + 1}/`}>Next →</a>        </li>      )}    </ul>  </nav>)}

補足:論理演算子(&&)について

論理演算子(&&)は、左辺が ture の時のみ(1ページしかないならナビゲーションを表示しない)右辺が適用されるようにします

JSX構文では、if 文の代わりによく使うテクニックで、AstroやReactでは

if (totalPages > 1) { return <nav>...</nav>}

という形より

{totalPages > 1 && <nav>...</nav>}

という書き方の方が簡潔でテンプレートに馴染みやすいです。

補足2:もっと複雑な条件を書くなら三項演算子

もっと複雑にすると、下記のように三項演算子で書くことが出来ます。

{totalPages === 0 ? <p>記事がありません</p> : <Pagination totalPages={totalPages} ... />}

ステップ②:スタイル(任意)

.pagination ul { display: flex; gap: 0.5rem; list-style: none; padding: 0;} .pagination li a,.pagination li span { display: inline-block; padding: 0.4em 0.8em; border: 1px solid #ccc; border-radius: 4px; text-decoration: none; color: #333;} .pagination li .current { font-weight: bold; background-color: #eee; pointer-events: none;}

前回ページに記述していたcssを、Pagination.astro に記述します。

Pagination.astro の全体は

--- const { totalPages, currentPage, baseUrl } = Astro.props;--- {totalPages > 1 && ( <nav class="pagination"> <ul> {currentPage > 1 && ( <li> <a href={`${baseUrl}${currentPage - 1}/`}>← Prev</a> </li> )} {Array.from({ length: totalPages }).map((_, i) => { const pageNum = i + 1; return ( <li> {pageNum === currentPage ? ( <span class="current">{pageNum}</span> ) : ( <a href={`${baseUrl}${pageNum}/`}>{pageNum}</a> )} </li> ); })} {currentPage < totalPages && ( <li> <a href={`${baseUrl}${currentPage + 1}/`}>Next →</a> </li> )} </ul> </nav>)} <style>.pagination ul { display: flex; gap: 0.5rem; list-style: none; padding: 0;} .pagination li a,.pagination li span { display: inline-block; padding: 0.4em 0.8em; border: 1px solid border-radius: 4px;  text-decoration: none;  color: }.pagination li .current {  font-weight: bold;  background-color:   pointer-events: none;}</style>

こんな感じです。

ステップ③:使い方(タグページ・カテゴリページなど)

例としてタグページに記述してみます!
タグページの css は必要ないので、style タグごと削除しておきます。

まずは script で Pagination.astro を import します!

import Pagination from '../../../../components/Pagination.astro';

そして、html に コンポーネントを記述して、コンポーネントのタグにコンポーネントに渡す props を記述しておきます。

<Pagination totalPages={totalPages} currentPage={currentPage} baseUrl={`/tags/${tag.slug}/page/`}/>

ビルドしてみると

ちゃんと出ました😀!

カテゴリーページに組み込んでみる

次はこのコンポーネントをカテゴリーページにも組み込んでみます。
カテゴリーのディレクトリ内にも、タグページ同様に、

/categories/[slug]/page/[page].astro

とファイルを作っておきます。
そしてそのファイルにスクリプトをhtmlを記述します。

---import Pagination from '../../../../components/Pagination.astro'; export async function getStaticPaths() { const res = await fetch('http://headless.local/wp-json/wp/v2/categories'); const categories = await res.json(); const paths = []; for (const category of categories) { const count = category.count; const totalPages = Math.ceil(count / 4); for (let page = 1; page <= totalPages; page++) { paths.push({ params: { slug: category.slug, page: page.toString(), }, props: { category, currentPage: page, }, }); } } return paths;}const { category, currentPage } = Astro.props;const totalPages = Math.ceil(category.count / 4); let posts = [];let fetchError = false; try { const res = await fetch(`http://headless.local/wp-json/wp/v2/posts?categories=${category.id}&per_page=4&page=${currentPage}&_embed`); if (!res.ok) throw new Error(`記事取得失敗: ${res.status}`); posts = await res.json();} catch (err) { console.error("記事取得エラー:", err); fetchError = true;}---<html lang="ja">  <head>    <meta charset="UTF-8" />    <title>{category.name} の記事一覧({currentPage}ページ目)</title>  </head>  <body>    <h1>カテゴリー: {category.name}</h1>    {fetchError ? (      <p style="color:red;">記事の取得に失敗しました。</p>    ) : posts.length === 0 ? (      <p>このカテゴリーには記事がありません。</p>    ) : (      <ul>        {posts.map(post => (          <li>            <a href={`/blog/${post.slug}/`}>              <h2>{post.title.rendered}</h2>              <p set:html={post.excerpt.rendered}></p>            </a>          </li>        ))}      </ul>    )}    <!-- ✅ ページネーションコンポーネントを表示 -->    <Pagination      totalPages={totalPages}      currentPage={currentPage}      baseUrl={`/categories/${category.slug}/page/`}    />    <p><a href="/categories/">← カテゴリー一覧に戻る</a></p>  </body></html>

/categories/overseas-travel/page/1/
にアクセスしてみると…

こちらにもページネーションが表示されました😆!

次回はリダイレクトの設定をします!



続きをみる


Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -

インモビ転職