動的ルーティング(2階層)

2023-03-18

以下のような場合に複数階層の動的ルーティングが発生する。

例)タグ別記事一覧ページのページ分け https://example.com/tags/[tag]/[page]

要点はgetStaticPaths() が何と返せばよいか?

タグの一覧を取得して、タグの一覧.map() でタグごとに該当する投稿を拾って、paginateでページ分けしたものを返す。

最終的に以下のような配列を返してくれればよい。

[
  { params: { tag: 'Astro', page: '1' }, props: { page: [Object] } },
  { params: { tag: 'blog', page: '1' }, props: { page: [Object] } },
  { params: { tag: 'blog', page: '2' }, props: { page: [Object] } },
  { params: { tag: 'knowledge', page: '1' }, props: { page: [Object] } },
]

なので以下のようになる。

---
import { getCollection } from 'astro:content';
import Layout from "../../../layouts/Layout.astro";
import Summary from "../../../components/Summary.astro";

export async function getStaticPaths({ paginate }) {
    const allPosts = await getCollection('posts');
    allPosts.sort((a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime())
    const tags = [...new Set(allPosts.map((post) => post.data.tags).flat())];
    return tags.map(tag => {
        const posts = allPosts.filter((post) => post.data.tags.includes(tag))
        return paginate(posts, { params:{ tag }, pageSize: 10 });
    }).flat()
}

const { tag } = Astro.params;
const { page } = Astro.props;
---

<Layout title={tag}>
    <h2>Posts tagged with {tag} <small class="fs-5">({page.currentPage}/{page.lastPage})</small></h2>
    <div>
{page.data.map((post) => <Summary post={post} />)}
    </div>
    <div>
        前のページリンク
        次のページリンク
    </div>
</Layout>