MENU

microCMSでAPIを用いてデータを取り出す②

【過去に書いたブログ記事のリライト版です】

目次

microCMSからAPIからデータを取り出す②

今回は前回に引き続き、microCMSを使ったデータの取り出し方についてまとめてみたいと思います。

【前回の記事はこちら】

今回の内容は、tagでブログ記事を絞り込む場合の書き方をまとめます。

microCMSからTagデータを取り出す

基本的にはblog記事のデータを取り出すときに使った手法と同じ手法を用います。

ただし、tagに応じて記事の取得内容が変わる、となると少し設定が必要になります。

これは、ブログ記事の詳細を表示するときのように、URLが選択した記事に応じて変わることを応用して作っていきます。

ファイル名の設定

ファイル名は[id].jsとして設定します。

これはNext.js側の設定になりますが、tagで記事の絞り込みをするとした場合、クリックしたtagに応じてURLが変わるようにしてあげたほうがわかりやすいです。

そこで、URLが絞り込みたいtagで切り替わる(動的に切り替わる)ように設定をする必要があります。

そのため、ファイル名には、[](ブラケット)を使用しファイル名を設定します。

今回は、microCMSでtagの登録をした際に、tag一つ一つに割り振られるidを利用してURLを生成することにしたいので、「[id].js」というファイル名で作成します。

pages/tags/[id].jsの設定

ここからは、pages/tags/[id].jsの中身についてまとめます。

初めに、全体のコードはこちらになります。

import Link from 'next/link'
import { client } from "../../libs/client"

// import Components
import Post from "../../components/Post";
import Tag from "../../components/Tag";



export default function Search({ blog, tag }) {
  return (
    <Layout title="Tag Search" description="This is the search page.Each content is sorted by tags contained.">
      <Container maxwidth="xl">
        <h2>Tag: { tag?.map((tag)=>(tag.name))} ( { blog.totalCount } 件)</h2>
        <Grid container>
          <Grid container spacing={1} xs={12} md={8} lg={8}>
            { blog.contents?.map((blog) => (
              <Grid item key={ blog.id } xs={12} sm={4} md={5} lg={4} xl={4}>
                <Grid container>
                  <Post
                    title = { blog.title }
                    description = { blog.description }
                    tags = { blog.tags }
                    writer = { blog.writer }
                    writerImage = { blog.writer.image.url }
                    slug = { blog.id }
                    date = { blog.publishedAt }
                    coverImage={ blog.ogimage.url }
                    related = { blog.related_blogs }
                  />
                </Grid>
              </Grid>
            ))}
          </Grid>
        </Grid>
      </Container>
    </Layout>
  )
}


export const getStaticPaths = async () => {
  const tags = await client.get({
    endpoint: "tags",
  })

  const paths = tags.contents.map((content) => `/tags/${content.id}`);
  return {
    paths,
    fallback: false
  }
};


export const getStaticProps = async( context ) => {
  const id = context.params.id;
  const blog = await client.get({
    endpoint: "blog",
    queries: {
      orders: '-createdAt',
      filters: `tags[contains]${id}`
    }
  })

  const tag = await client.get({
    endpoint: "tags",
    queries: {
      filters: `id[equals]${id}`
    }
  })

  return {
    props: {
      tag: tag.contents,
      blog: blog,
    }
  }
}

動的なURLの設定

ここでは、動的にURLが切り替わるように設定する必要があるため、以下のように設定しています。

export const getStaticPaths = async () => {
  const tags = await client.get({
    endpoint: "tags",
  })
  const paths = tags.contents.map((content) => `/tags/${content.id}`);

  return {
    paths,
    fallback: false
  }
};

getStaticPathsという関数を使用します。

Next.js側ではtagidがわからないため、事前にURLの生成をすることができません。

そこでこの関数内でデータを取得し、パスを定義してあげています。

ここでのパスはmicroCMSでtagの登録をした際に、tag毎に割り振られるidを使用しています。

またfallbackfalseにしています。

これで、getStaticPathsで返されないパスをすべて404ページで返すようにしています。

まずは、getStaticPathsの関数内で、

const tags = await client.get({
    endpoint: "tags",
  })

を定義することで、microCMSで作成したtagsコンテンツの一覧を取得します。

これは、ブログの記事を取り出したときと何も違いはありません。

そして次に、

const paths = tags.contents.map((content) => `/tags/${content.id}`);

によりpathsという定数を定義します。

先ほど取り出したtagsの中身から、tagidを取り出し、URLの生成をする際に渡します。

これにより、tagidに応じた絞り込み用のURLを生成するように設定します。

この生成されたURLを使用したルーティングによりHTMLを生成するページURLをNext.js側も認識することができるため、個々のtagによる絞り込みをした結果を返すページのURLが認識されるようになるわけです。

ちなみに、私のブログの場合、tagsの中身は、このように生成されています。

{
    "contents": [
        {
            "id": "tagに割り振られるid①",
            "createdAt": "2021-07-13T22:23:09.410Z",
            "updatedAt": "2021-07-14T11:59:30.890Z",
            "publishedAt": "2021-07-13T22:23:09.410Z",
            "revisedAt": "2021-07-14T11:59:30.890Z",
            "name": "tagに設定されるtag名①"
        },
        {
            "id": "tagに割り振られるid②",
            "createdAt": "2021-07-13T22:22:53.922Z",
            "updatedAt": "2021-07-13T22:22:53.922Z",
            "publishedAt": "2021-07-13T22:22:53.922Z",
            "revisedAt": "2021-07-13T22:22:53.922Z",
            "name": "tagに設定されるtag名②"
        },
}

つまり、tagsを取り出すと上記のような配列によりデータが取り出されるので、pathsを定義する際には、map関数で配列の中身を取り出して、URLを生成しています。

そして、「tagsの中にあるcontents配列の中のtag一つ一つのidを取り出す」ので、map関数で取り出す際は、

tags.contents

までを取り出し、map関数で取り出してあげます。

私の場合は、これで取り出した中身をcontentという引数に受けて、その中身のidを取り出しているという形をとっています。

データをテンプレートに渡す設定

次に、getStaticProps関数の設定をしていきます。

これは、表示するページに渡されるデータを取得したり、それを受け渡すための設定をする関数になります。

getStaticPropsの全体は以下のとおり。

export const getStaticProps = async( context ) => {
  const id = context.params.id;
  const blog = await client.get({
    endpoint: "blog",
    queries: {
      orders: '-createdAt',
      filters: `tags[contains]${id}`
    }
  })

  const tag = await client.get({
    endpoint: "tags",
    queries: {
      filters: `id[equals]${id}`
    }
  })

  return {
    props: {
      tag: tag.contents,
      blog: blog,
    }
  }
}

それでは一つずつ見ていきます。

idにparamsを受ける

一行目で、getStaticProps関数の引数であるcontextからidに代入されています。

const id = context.params.id;

Next.jsのcontext パラメーターは、paramsというキーを持つオブジェクトです(もちろん他にも持っているキーはありますが)。

例えば、このcontextが持っているparamsキーは、

paths: [
    { params: { id: '1' } },
    { params: { id: '2' } }
],

のように、idを返し、pages/tags/[id].jsの表示では、pages/tags/1pages/tags/2のようなURLを生成し、そのページを表示します。

今回のtagの絞り込みでは、このparamsキーにgetStaticPathsによりtagidが渡されているため、これをgetStaticProps内で受け取ります。

この受け取ったtagidは後ほどtagの絞り込みに使用します。

ブログデータの取り出し

ブログデータを取り出す際は、先ほど設定したtagid(中身はcontext.params.id)を用いてブログ記事の絞り込みを行います。

これは、microCMSからデータを取り出す際に、データを絞り込みをした状態で取り出すよう設定しています。

const blog = await client.get({
    endpoint: "blog",
    queries: {
      orders: '-createdAt',
      filters: `tags[contains]${id}`
    }
  })

データの取り出しについては、通常のデータ取り出しとほとんど変わりません。

しかし、queriesの設定で、filters: `tags[contains]${id}`を設定しています。

これはmicroCMSのデータ取り出し方法の設定になりますが、公式にはこのように記載されています。

filtersというqueryを設定することで、データを絞り込んだ状態で抽出することができるようです。

そして、今回はブログデータの持つtagsデータに今回絞り込みたいtagが含まれているかどうかを指定することでデータを絞り込みしていきます。

(ブログが持っているtagsのデータにも、個々のtagが持つidを持たされていることから、絞り込みたいtagidを含むかどうかによりデータの絞り込みをしているというわけです。)

そして、先ほどcontext.params.idで取り出したgetStaticPathsにより渡されているtagidを使って絞り込みます。

この時設定するfiltersは「tags[contains]${id}」としています。

設定自体は公式のとおりですが、受け取ったtagidを「${id}」として組み込んでいます。

これにより、絞り込みする際に使用するidgetStaticPathsにより渡されるtagidになるため、毎回絞り込みを行うさいに個々のidが渡されるため、絞り込みの結果がtagidにより変わるということになります。

これで絞り込んだデータの取り出し設定は完了です。

データを返して、表示する

データの返し方は、

return {
    props: {
      tag: tag.contents,
      blog: blog,
    }
  }

のように、特段これまでと変更はありません。

ですが、今回の場合は、tagには「.contents」をつけ、blogには「.contents」をつけていません。

これはなぜかというと、tagblogデータを取り出すときにmicroCMSでは「totalCount」というデータも一緒に出力されています。

これは、contentsと同じ階層にあるため、データを渡す際に「.contents」まで指定してしまうとtotalCountが取り出せなくなるためです。

絞り込んだブログデータの件数をtotalCountとして返してくれているため、これを使って抽出時の件数を拾って、表示しているわけです。

HTMLへの出力は、このようになります。

return (
    <Layout title="Tag Search" description="This is the search page.Each content is sorted by tags contained.">
      <Container maxwidth="xl">
        <h2>Tag: { tag?.map((tag)=>(tag.name))} ( { blog.totalCount } 件)</h2>
        <Grid container>
          <Grid container spacing={1} xs={12} md={8} lg={8}>
            { blog.contents?.map((blog) => (
              <Grid item key={ blog.id } xs={12} sm={4} md={5} lg={4} xl={4}>
                <Grid container>
                  <Post
                    title = { blog.title }
                    description = { blog.description }
                    tags = { blog.tags }
                    writer = { blog.writer }
                    writerImage = { blog.writer.image.url }
                    slug = { blog.id }
                    date = { blog.publishedAt }
                    coverImage={ blog.ogimage.url }
                    related = { blog.related_blogs }
                  />
                </Grid>
              </Grid>
            ))}
          </Grid>
        </Grid>
      </Container>
    </Layout>
  )

Material-UIGrid componentなどを使用していますが、こちらの設定は省略します。

最後に

今回は、データの絞り込みについてまとめてみました。

設定した個々のデータがidを持ち合わせていることで、このidを使用した絞り込みができるのは便利ですね。

さらに、microCMSサイドでデータの絞り込みをすることができる設定があるのも便利です。

他にもデータの取り出し方法や設定はあるようなので、今後も少しずつ学習を進めていきたいと思います。

今回はここまででとなります。

最後まで読んでいただきありがとうございました!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次