Tailwind Logo

Nextjs の App Route の Dynamic Routes を利用してブログのページを作る(中編)

Content Hub ONENext.js

公開日: 2024-08-22

前回、ブログの個別のページに関して、Dynamic Route で ID を利用して作成する手順を紹介しました。今回はもう1つ改善して、URL のパスに日付と Slug を利用して処理できるように進めていきます。

Slug と日付を確認

前回、タイトルだけを表示していたブログの記事で、PublishDate と Slug を取得できているかを app/blog/[slug]/page.tsx のファイルを書き換えて確認します。

TypeScript
  return (
    <>
      <div>Title: {post.title}</div>
      <div>Publish Date: {post.publishDate}</div>
      <div>Slug: {post.slug}</div>
    </>
  );

実際に publishDate および slug が表示されます。

nextappdynamicroute05.png

ページで必要なデータの取得ができているのを確認しました。

ID から Slug に切り替える

URL として利用していた値を ID から Slug の値に変更をします。まず、Slug を利用してブログの記事を表示するために、 Slug の値が同じブログの記事を取得するクエリを作成します。今回はサンプルの記事を利用して以下のように作成しました。

GraphQL
query AllBlog {
    allBlog(where: { slug_eq: "introducing-sitecore-composable-dxp-products" }) {
        total
        results {
            description
            id
            name
            publishDate
            slug
            title
            body
            image {
                total
                results {
                    description
                    fileHeight
                    fileId
                    fileName
                    fileSize
                    fileType
                    fileUrl
                    fileWidth
                    id
                    name
                }
            }
        }
    }
}

Postman で以下のようにデータの取得が出来ていることがわかります。

nextappdynamicroute02.png

呼び出しをするための定義を src/interfaces/Blog/index.ts に追加します。

TypeScript
export const BlogFromSlugQuery = (slug: string) => {
  return `
  query AllBlog {
    allBlog(where: { slug_eq: "${slug}" }) {
        total
        results {
            description
            id
            name
            publishDate
            slug
            title
            body
            image {
                total
                results {
                    description
                    fileHeight
                    fileId
                    fileName
                    fileSize
                    fileType
                    fileUrl
                    fileWidth
                    id
                    name
                }
            }
        }
    }
}
  `
}

上記では slug の値を渡して呼び出しをするようにしました。このクエリは全てのブログの記事から Slug の値が同じものを取得する形です。このため Slug にはユニークな値を設定するようにします。続いて記事を取得する関数を定義している、src/utils/getBlog/index.ts に、以下のコードを追加します。

TypeScript
export async function getBlogFromSlug(slug: string): Promise<Partial<Blog>> {
    const results: AllBlogResponse = (await fetchGraphQL(
        BlogFromSlugQuery(slug)
    )) as AllBlogResponse;

    return results.data.allBlog.results[0];
}

これで Slug を利用して該当する記事を取得することが可能となります。なお Slug が重複して登録されている場合でも1つめの結果を取得する形としています。

では実際に slug を URL で利用するために、 app/blog/[slug]/page.tsx のファイルで、ページで取得するコードを以下のように変更します。

TypeScript
  const post = await getBlogFromSlug(params.slug);

これで Slug の値を利用してページを表示します。テストをしやすいように、トップページのapp/page.tsx のファイルの出力部分も以下のように変更します。

TypeScript
    <main>
      <h1>Content Hub ONE - Title list</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <Link href={`/blog/${post.slug}`}>{post.title}</Link>
          </li>
        ))}
      </ul>
    </main>

実行をすると、以下のように slug を利用してブログのページが表示されていることがわかります。

nextappdynamicroute06.png

日付を URL に設定する

最後に、 Slug だけでなく、URL を YYYY/MM/DD/Slug という形で URL を設定できるように Dynamic Routes を設定したいと思います。複数のパスを利用できるようにするためには、 Catch-all Segments を利用することになるため、パスを [...slug] に変更をします。

変更後のファイル src/app/blog/[...slug]/page.tsx において、4 つ目の値が slug という扱いになるため、params.slug[3] で slug を取得するように以下のように書き換えます。

TypeScript
export default async function Page({ params }: { params: { slug: string } }) {
  const post = await getBlogFromSlug(params.slug[3]);

これで日付などを指定したあと、URL に日付を入れることが可能となりました。

nextappdynamicroute04.png

まとめ

今回は Slug として利用するフィールドを追加して URL に関して制御できるようにする手順を紹介しました。しかしながら、日付に関してのところは指定できるようにしただけで、今のところ何も指定していません。これは次回実装していきます。サンプルとして表示しているコンテンツは title だけですが、データとしては取得できているので、あとはブログのページを作ったりしていく形です。

関連ページ

関連タグ