GatsbyJS マークダウンにコンポーネントを表示する

2019-07-10

unsplashのランダム画像を表示するコンポーネントを作成し、マークダウン内でunsplash要素として使用できるようにします。

必要なプラグイン

以前使ったマークダウンの表示に必要なプラグイン 詳しくはこちら

  • gatsby-source-filesystem
  • gatsby-transformer-remark

今回必要なプラグイン

  • rehype-react
    マークダウンの要素を変換するReactのプラグイン
  • gatsby-remark-component
    マークダウン表示時のpタグをdivタグに変換する (変換しないとvalidateDOMNestingアラートがでてしまう)
npm install --save rehype-react gatsby-remark-component

まずはマークダウンファイルをそのまま表示

マークダウンファイルを作成

プロジェクトディレクトリにdataディレクトリを作成し、file1.mdを作成する

## マークダウンファイルの内容

AAAABBBBCCCCDDDD  
あああいいいうううえええおお  
000111222333444  

gatsby-config.jsの修正

利用するプラグインとdataディレクトリを検索するように指定

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `data`,
        path: `${__dirname}/data/`,
      },
    },
    `gatsby-transformer-remark`,
  ],
}

index.jsでfile1.mdの内容を表示する

markdownRemarklでhtmlを取得し、表示するだけのindex.jsを作成

// index.js
import React from "react"
import { graphql } from "gatsby"

export default ({ data }) => {
    const post = data.markdownRemark
    return (
        <div>
            <div dangerouslySetInnerHTML={{ __html: post.html }} />
        </div>
        )
    }

    // 今回はマークダウンが1つなので条件を指定せず、markdownRemarkで取得
    export const query = graphql`
    query {
        markdownRemark {
            html
        }
      }
`

開発サーバを起動し、ブラウザ表示するとマークダウンの内容が表示されます。

gatsby_markdown_1

unsplashコンポーネントを作成し、マークダウン内で使用する

gatsby-config.jsの修正

gatsby-transformer-remarkのオプションとしてgatsby-remark-componentを記述します。

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `data`,
        path: `${__dirname}/data/`,
      },
    },
    {
      resolve: "gatsby-transformer-remark",
      options: {
        plugins: [
          {
            resolve: "gatsby-remark-component",
            //変換する要素を指定したいときはoptionに記載する
            // options: { components: ["my-component", "other-component"] }
          }
        ]
      }
    }
  ],
}

コンポーネントの作成

unsplashのランダム画像を表示するコンポーネントUnsplashを作成する。(src\components\Unsplash.jsを作成)
せっかくなので引数でサイズの指定をできるようにします。

import React from 'react'

const Unsplash = (data) => {
    const url = `https://source.unsplash.com/random/${data.size}`
    return(
        <div>
            <img src={url} />
        </div>
    )
}
export default Unsplash

index.jsの変更

index.jsには以下の修正を行います。

  1. rehype-react、Unsplashをインポートする
  2. GraphQLの取得内容をhtmlからhtmlAstに変更
  3. rehypeReactを使い、unsplash要素とUnsplashコンポーネントをマッピング
  4. dangerouslySetInnerHTMLで表示していた箇所をrenderAstに変更
// index.js
import React from "react"
import { graphql } from "gatsby"
// 1. rehype-react、Unsplashをインポートする
import rehypeReact from "rehype-react"
import Unsplash from "../components/Unsplash"


// 3. rehypeReactを使い、unsplash要素とUnsplashコンポーネントをマッピング
const renderAst = new rehypeReact({
    createElement: React.createElement,
    components: { "unsplash": Unsplash},//keyの指定は小文字
  }).Compiler

export default ({ data }) => {
    const post = data.markdownRemark
    return (
        <div>
        {/* 4. dangerouslySetInnerHTMLで表示していた箇所をrenderAstに変更 */}
          {renderAst(post.htmlAst)}
        </div>
        )
    }

    // 2. GraphQLの取得内容をhtmlからhtmlAstに変更
    export const query = graphql`
    query {
        markdownRemark {
            htmlAst
        }
      }
`

マークダウンファイルにunsplash要素をいれる

マークダウンに<unsplash></unsplash>を記述して、動作を確認する。
<unsplash />はNG。

## マークダウンファイルの内容

AAAABBBBCCCCDDDD  
あああいいいうううえええおお  
000111222333444  

画像の表示
<unsplash size="400x200"></unsplash>


サイズ指定なしの画像の表示
<unsplash></unsplash>

動作確認

開発サーバを起動すると画像の表示が確認できます。

gatsby_markdown_2

gatsby-remark-componentを使わない時の警告

gatsby-remark-componentを使用すると、コンポーネントを囲っているタグがpからdivに変わっている。

gatsby_markdown_3

pタグのままだと裏で警告が出ている。

gatsby_markdown_4

validateDOMNesting(...): <div> cannot appear as a descendant of <p>.

pタグはインライン要素なので、ブロック要素のdivタグをネストするのは不適切とのこと。

■同じタグの記事(最新5件)
GatsbyJS FaunaDBからデータを取得する
GatsbyJS 検索機能を実装する(JsSearchを利用)
GatsbyJS PostgreSQLの内容を取得する
GatsbyJS rehypeReactでマークダウンの内容を変更する
GatsbyJS トランスフォーマープラグインを使用してマークダウン...
■同じタグの記事を見る