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
}
}
`
開発サーバを起動し、ブラウザ表示するとマークダウンの内容が表示されます。
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 には以下の修正を行います。
- rehype-react、Unsplash をインポートする
- GraphQL の取得内容を html から htmlAst に変更
- rehypeReact を使い、unsplash 要素と Unsplash コンポーネントをマッピング
- 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-remark-component を使わない時の警告
gatsby-remark-component を使用すると、コンポーネントを囲っているタグが p から div に変わっている。
p タグのままだと裏で警告が出ている。
validateDOMNesting(...): <div> cannot appear as a descendant of <p>.
p タグはインライン要素なので、ブロック要素の div タグをネストするのは不適切とのこと。