Tailwind Logo

Next.js の Fetch を利用してコンテンツ一覧を取得する

Content Hub ONENext.js

公開日: 2024-08-07

Next.js には fetch の機能を利用して、外部のデータを取得して処理をするための仕組みが含まれています。今回はこれを利用して、Blog のタイトルを取得したいと思います。

API を作成する

プロジェクトで汎用的に利用できる API として、GraphQL のクエリの値を取得したらデータを返す、という関数を作成します。実際に作成したコードは以下の URL をクリックすることで、GitHub 上で全コードを見ることができます。

動作としては以下のような記述をしています。

  • fetchGraphQL には query を文字列として渡す
    • apiKey および endpointUrl の値は .env.local のファイルから読み込んでいます
  • fetch 関数を利用して、上記で指定した endpointUrl に対して、apiKey を利用してクエリを Post します。
  • 正しく json のデータを取得できたとき、json のデータを返しています。

これで GraphQL のクエリを利用して fetchGraphQL を利用して Json のデータを取得できるようになります。

なお、fetch を利用している際に以下のような呼び出しをしています。

TypeScript
    return await fetch(endpointUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-GQL-Token": apiKey,
      },
      body: JSON.stringify({ query }),
      next: { revalidate: 60 },
    })

GraphQL のエンドポイントに対して最後に next: { revalidate: 60 } の記述があります。クエリを実行する際に 60 秒ごとに更新されて、キャッシュされています。

Query を定義する

作成をした fetchGraphQL に渡す Query の定義を追加します。今回は、interfaces/blog/index.ts のファイルに以下のコードを追加しました。前回作成をした AllBlog のクエリを利用しながら、並び順をブログの新着順にして AllBlogQuery とし、かつ今回は最小限のデータを取得するだけとしています。

TypeScript
export const AllBlogQuery = `query AllBlog {
    allBlog(orderBy: PUBLISHDATE_DESC) {
        total
        results {
            id
            name
            publishDate
            slug
            title
            description
        }
    }
}
`

Postman で実行した結果としては、以下のようにデータを取得できています。

choneblog01.png

page.tsx の変更

準備が整いました。Next.js のトップページとなる app/page.tsx をガラリと変更して以下のように更新しています。

TypeScript
import { fetchGraphQL } from "@/utils";
import { Blog, AllBlogResponse, AllBlogQuery } from "@/interfaces/Blog";

export default async function Home() {
  const results: AllBlogResponse = (await fetchGraphQL(
    AllBlogQuery
  )) as AllBlogResponse;

  const posts: Partial<Blog>[] = [];

  results.data.allBlog.results.forEach((post: Partial<Blog>) => {
    posts.push({
      id: post.id,
      name: post.name,
      publishDate: post.publishDate,
      slug: post.slug,
      title: post.title,
      description: post.description,
    });
  });

  return (
    <main>
      <h1>Content Hub ONE - Title list</h1>
      <ul>
        {posts.map((post) => (
            <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </main>
  );
}

コードを上から紹介していくと、

  • import で事前に作成したコードの読み込み
  • データを Query を利用して AllBlogResponse として取得
  • AllBlogResponse のデータを posts という Blog の配列に変換
  • posts にあるタイトルのみを抜き出して並べる

というごく簡単なコードとなっています。結果は以下の通りです。

choneblog02.png

GitHub に反映させる

まず上記のコードを development ブランチに対して適用します。以前に Vercel の development ブランチに連携している staging 環境に対しては、Preview の値を設定していたため、未公開のコンテンツも表示されています。

choneblog03.png

今度は development ブランチのデータを main ブランチに反映させます。コンテンツは1つだけが Publish されているだけのため、以下のように1本のみコンテンツが表示されています。

choneblog04.png

まとめ

実際に Next.js のトップページを変更する形で、コンテンツの一覧を表示しました。環境変数を利用して、staging と production でそれぞれコンテンツの表示先が異なることも確認できました。トップページでタイトルを表示しているのみではありますが、データを取得して表示ができれば、最初の一歩という形になります。

ここまでのコードを以下のブランチで保存しています。

関連タグ