初心者による初心者のためのGatsbyJS覚書8（ブログの記事ページを作成する）

#この記事について
この記事はGatsbyJS初心者の新卒２年目が作成しています。
参考資料として書籍を使用していますが、筆者がビギナークラスのため読んでいて「？」となる部分や間違っている箇所もあるかと思います。
参考までに、そして間違えている箇所がありましたらご連絡いただけると嬉しいです。

##Chapter8：ブログの記事ページを作成する　備忘録メモ

1.記事ページを作成する
2.記事の内容を表示する
3.記事のアイキャッチ画像を表示する
4.リッチテキストを表示する

###記事ページを作成する

`pages`配下に`blogpost.js`を作成してベースのHTMLをJSXに変換してページが表示できるか確認する。

```jsx
import React from "react"
import Layout from "../components/layout"

const BlogPost = () => (
  <Layout>
  
  //ここにJSXを記載

  </Layout>
)

export default BlogPost
```
参考書籍の工程上、記事にアイコンを表示する手順があるが別記事で解説しているのでここでは割愛します。
URLに`/blogpost`を追加してページの表示を確認してみる。

###記事の内容を表示する

記事の中にcontentfulのデータを出力していく。
ここでは下記データを出していく。

* タイトル
* 投稿日
* カテゴリー

```jsx
import React from "react"
import Layout from "../components/layout"
import { graphql } from "gatsby"

const BlogPost = () => (
  <Layout>
  　　//タイトル
  　　<h1 className="bar">{data.contentfulBlogPost.title}</h1>

　　　　　　//投稿日
  　　<time dateTime={data.contentfulBlogPost.publishDate}>{data.contentfulBlogPost.publishDateJP}</time>

　　　　　//カテゴリー
  　　<ul>
  　　{data.contentfulBlogPost.category.map(cat => (
    <li className={cat.categorySlug} key={cat.id}>
      {cat.category}
    </li>
  ))}
  </ul>
  </Layout>
)

export const query = graphql`
query MyQuery {
  contentfulBlogPost {
    title
    publishDateJP: publishDate(formatString: "YYYY年MM月DD日")
    publishDate
    category {
      categorySlug
      category
      id
    }
  }
}
`
export default BlogPost
```

###記事のアイキャッチ画像を表示する

他記事で画像の出し方についても解説しているのでコードのみ記載。

```jsx
import React from "react"
import Layout from "../components/layout"
import { graphql } from "gatsby"
import { GatsbyImage } from "gatsby-plugin-image" //追加

const BlogPost = () => (
  <Layout>
  　　//アイキャッチ
    <GatsbyImage image={data.contentfulBlogPost.eyecatch.gatsbyImageData}
     alt={data.contentfulBlogPost.eyecatch.description}/>
  </Layout>
)

export const query = graphql`
query MyQuery {
  contentfulBlogPost {
    title
    publishDateJP: publishDate(formatString: "YYYY年MM月DD日")
    publishDate
    category {
      categorySlug
      category
      id
    }
    eyecatch {
      gatsbyImageData(layout: FULL_WIDTH)
      description
      file {
        details {
          image {
            height
            width
          }
        }
        url
      }
    }
  }
}
`
export default BlogPost
```
###リッチテキストを表示する

リッチテキストで入力されたデータを表示していく。

```jsx

import React from "react"
import Layout from "../components/layout"
import { graphql } from "gatsby"
import { GatsbyImage } from "gatsby-plugin-image" //追加
import { renderRichText } from "gatsby-source-contentful/rich-text"
import { BLOCKS } from "@contentful/rich-text-types"

const options = {
  renderNode: {
    [BLOCKS.HEADING_2]: (node, children) => (
      <h2>
        <FontAwesomeIcon icon={faCheckSquare} />
        {children}
      </h2>
    ),
    [BLOCKS.EMBEDDED_ASSET]: node => (
      <GatsbyImage
        image={node.data.target.gatsbyImageData}
        alt={
          node.data.target.description
            ? node.data.target.description
            : node.data.target.title
        }
      />
    ),
  },
  renderText: text => {
    return text.split("\n").reduce((children, textSegment, index) => {
      return [...children, index > 0 && <br key={index} />, textSegment]
    }, [])
  },
}
const BlogPost = () => (
  <Layout>
  　　//本文
 　　　　<div className="postbody">
    {renderRichText(data.contentfulBlogPost.content, options)}
　　　　　　</div>
  </Layout>
)

export const query = graphql`
query MyQuery {
  contentfulBlogPost {
    title
    publishDateJP: publishDate(formatString: "YYYY年MM月DD日")
    publishDate
    category {
      categorySlug
      category
      id
    }
    eyecatch {
      gatsbyImageData(layout: FULL_WIDTH)
      description
      file {
        details {
          image {
            height
            width
          }
        }
        url
      }
    }
    content {
      raw
      references {
        ... on ContentfulAsset {
          contentful_id
          gatsbyImageData(layout: FULL_WIDTH)
          title
          description
        }
      }
    }
  }
}
`
export default BlogPost
```