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