CodeCode

なんか色々おぼえ書き。だいたいweb制作関連。

Astro.jsとWP REST APIを使ったブログにページネーションをつける

前回作ったブログの記事一覧にページネーションをつけていきます。

記事一覧にページネーションを追加する

/src/pages/index.astroを編集します。

---
const res = await fetch("https://cms.codecodeweb.com/wp-json/wp/v2/posts?_embed&per_page=10")
const posts = await res.json()
const total = await res.headers.get('x-wp-totalpages')
---

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>CodeCode</title>
</head>
<body>
    
    <h1>CodeCode</h1>
    
    {
        posts.map((post) => (
            <h2>
                <a href={`/posts/${post.id}/`} set:html={post.title.rendered} />
            </h2>
            <p set:html={post.excerpt.rendered} />
        ))
    }
    
    <div class="pagenation">
        <ul>
            {
                [...Array(Number(total))].map((post, index) => (
                    <li><a href={`/page/${index + 1}/`}>{index + 1}</a></li>
                ))
            }
        </ul>
    </div>
    
</body>
</html>

記事をfetchする際に、HTTPヘッダに含まれている総ページ数の情報を取得します。

HTTPヘッダのx-wp-totalpagesを取得します。

const total = await res.headers.get('x-wp-totalpages')

総記事数が40(2023年3月16日現在)なので、10件ずつ取得するとx-wp-totalpagesは4になります。

それを使って空の配列を作り、それをmapで回して第二引数のindexを使ってページの数字を出力します。

配列の添字は0から始まるので +1 しています。

<div class="pagenation">
    <ul>
        {
            [...Array(Number(total))].map((post, index) => (
                <li><a href={`/page/${index + 1}/`}>{index + 1}</a></li>
            ))
        }
    </ul>
</div>

ページネーションで遷移後のページ

/src/pages/pageディレクトリを作り、[page].astroを作ります。

動的にページ数が変わるので、記事詳細ページ同様ファイル名は[page].astroとします。

---
export async function getStaticPaths() {
    let data = await fetch(`https://cms.codecodeweb.com/wp-json/wp/v2/posts?_embed&page=1&per_page=10`)
    let total = await data.headers.get('x-wp-totalpages')
    
    // 該当するパラーメータ分出力
    //ページ数なので最大ページ数分配列を生成
    return [...Array(Number(total))].map((param, index) => (
        [
            {
                params: {page: index + 1},
            }
        ]
    ))
}
---

Dynamic routesを使用する際はgetStaticPaths関数が必要なので、その中で総ページ数を取得するためにfetchします。

その総ページ数を使い総ページ数分のparamsの入った配列を作ります。

続いて、getStaticPaths関数の外に、Astro.paramsで取得したパラメーターを元に現在のページ情報を表示するコードを追記します。

const { page } = Astro.params;

let res = await fetch(`https://cms.codecodeweb.com/wp-json/wp/v2/posts?_embed&page=${page}&per_page=10`)
let posts = await res.json();
let total = await res.headers.get('x-wp-totalpages')

以降は、index.astroの記事一覧と同様に記事を出力します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>CodeCode</title>
</head>
<body>
    
    <h1>CodeCode</h1>
    
    {
        posts.map((post) => (
            <h2>
                <a href={`/posts/${post.id}/`} set:html={post.title.rendered} />
            </h2>
            <p set:html={post.excerpt.rendered} />
        ))
    }
    
    <div class="pagenation">
        <ul>
            {
                [...Array(Number(total))].map((post, index) => (
                    <li><a href={`/page/${index + 1}/`}>{index + 1}</a></li>
                ))
            }
        </ul>
    </div>
    
</body>
</html>

Build

npm run build

するとdistにHTMLが出力されます。

postsの中には記事IDのディレクトリができて、ページのHTMLが出力されています。

今回は総記事数が40(2023年3月16日現在)なので、10件ずつ取得しているので、pageの中には4ページ出力されています。

dist
├── _astro
   └── index.974901e5.css
├── favicon.svg
├── index.html
├── page
   ├── 1
   └── index.html
   ├── 2
   └── index.html
   ├── 3
   └── index.html
   └── 4
       └── index.html
└── posts
    ├── 110
   └── index.html
 ~中略~
    └── 98
        └── index.html
TOPへ戻る