gatsby入門 チュートリアルをこなす 7. プログラムでデータからページを作成する

2020年09月06日

JavaScript JSX React gatsby

gatsbyの作業履歴

gatsby入門 チュートリアルをこなす 0.開発環境をセットアップする gatsby入門 チュートリアルをこなす 1. ギャツビービルディングブロックについて知る(1) gatsby入門 チュートリアルをこなす 1. ギャツビービルディングブロックについて知る(2) gatsby入門 チュートリアルをこなす 2. ギャツビーのスタイリングの概要 gatsby入門 チュートリアルをこなす 3. ネストされたレイアウトコンポーネントの作成 gatsby入門 チュートリアルをこなす 4. ギャツビーのデータ gatsby入門 チュートリアルをこなす 5. ソースプラグインとクエリされたデータのレンダリング gatsby入門 チュートリアルをこなす 6. 変圧器プラグイン※Transformer pluginsのgoogle翻訳 今回:gatsby入門 チュートリアルをこなす 7. プログラムでデータからページを作成する gatsby入門 チュートリアルをこなす 8. 公開するサイトの準備 gatsby入門 ブログ作ってサーバーにアップしてみる

チュートリアル

今回実施するgatsbyのチュートリアルはこちら https://www.gatsbyjs.com/tutorial/part-seven/ チュートリアルの冒頭にこう書かれています。

Reactコンポーネントをsrc / pagesに配置することで、引き続きページを作成できます。ただし、プログラムからデータからページを作成する方法を学習します。

※google翻訳です。 早速やっていきましょう。 ソースは前回作ったやつを使用します。

Programmatically create pages from data

Creating slugs for pages

マークダウンページを作成するには、onCreateNodeとcreatePagesの2つのGatsby APIを使用します。 gatsby-node.jsを作成し、以下を記述します。

exports.onCreateNode = ({ node }) => {
  console.log(`Node created of type "${node.internal.type}"`)
}

チュートリアルはこのように記載されています。

このonCreateNode関数は、新しいノードが作成(または更新)されるたびにGatsbyによって呼び出されます。

なるほど。 gatsby開発サーバを再起動します。 起動はgatsby developでできます。 2020-09-06_02h21_53.jpg なんかログがいっぱい出てその中にマークダウンの文字が。 gatsby-node.jsを修正します。

exports.onCreateNode = ({ node }) => {
  ↓ここから
  if (node.internal.type === `MarkdownRemark`) {
    console.log(node.internal.type)
  }
  ↑ここまで修正
}

マークダウンだけログだしするのね。 再起動 2020-09-06_02h26_55.jpg 出てる出てる マークダウンファイルのファイル名からURLのパスを作っていきましょう。 。。gatsbyだとパスをslugっていうのか。 gatsby-node.jsを修正

exports.onCreateNode = ({ node, getNode }) => {←ここ修正
  if (node.internal.type === `MarkdownRemark`) {
    const fileNode = getNode(node.parent)←ここ修正
    console.log(`\n`, fileNode.relativePath)←ここ修正
  }
}

再起動 2020-09-06_02h32_44.jpg これか! ここからgatsby-source-filesystem pluginを使用 gatsby-node.jsを修正

const { createFilePath } = require(`gatsby-source-filesystem`)←ここ追記

exports.onCreateNode = ({ node, getNode }) => {
  if (node.internal.type === `MarkdownRemark`) {
    console.log(createFilePath({ node, getNode, basePath: `pages` }))←ここ修正
  }
}

再起動 2020-09-06_02h36_42.jpg 出来てる! ここからcreateNodeFieldを使用してslug(パス)を作ります。 gatsby-node.jsを修正

const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {←ここ修正
  const { createNodeField } = actions←ここ修正
  if (node.internal.type === `MarkdownRemark`) {
    ↓ここから
    const slug = createFilePath({ node, getNode, basePath: `pages` })
    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })
    ↑ここまで追記
  }
}

再起動 GraphiQLで以下を実行

query MyQuery {
  allMarkdownRemark {
    edges {
      node {
        fields {
          slug
        }
      }
    }
  }
}

2020-09-06_02h45_04.jpg キタコレ!

Creating pages

ページ作りだ! gatsby-node.jsを修正

const { createFilePath } = require(`gatsby-source-filesystem`)

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })
    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })
  }
}

↓ここから
exports.createPages = async ({ graphql, actions }) => {
  // **Note:** The graphql function call returns a Promise
  // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise for more info
  const result = await graphql(`
    query {
      allMarkdownRemark {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }
  `)
  console.log(JSON.stringify(result, null, 4))
}
↑ここまで追記

この時点でどうなるのかさっぱりわからんが続けよう。 src/templatesディレクトリを作成 src/templates/blog-post.jsを作成し以下を記述

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

export default function BlogPost() {
  return (
    <Layout>
      <div>Hello blog post</div>
    </Layout>
  )
}

gatsby-node.jsを修正

const path = require(`path`)←ここ追記
const { createFilePath } = require(`gatsby-source-filesystem`)

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions
  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })
    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })
  }
}

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions←ここ追記
  const result = await graphql(`
    query {
      allMarkdownRemark {
        edges {
          node {
            fields {
              slug
            }
          }
        }
      }
    }
  `)
  ↓ここから
  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: node.fields.slug,
      component: path.resolve(`./src/templates/blog-post.js`),
      context: {
        // Data passed to context is available
        // in page queries as GraphQL variables.
        slug: node.fields.slug,
      },
    })
  })
  ↑ここまで追記
}

再起動 以下でアクセス http://localhost:8000/sdf ※sdfは何でもいい 2020-09-06_03h00_20.jpg あ、パスが出来てる アクセス 2020-09-06_03h01_14.jpg マークダウンファイルはまだ出てこない。 なるほど、ちょっとわかったぞ。 gatsby-node.jsのonCreateNodeでマークダウンのファイル名を取得してslug(パス)を作成。 createPagesでそのslugを取得し、繰り返し処理の中でパスとsrc/templates/blog-post.jsを同期させるのね! つづき! src/templates/blog-post.jsの修正

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

export default function BlogPost({ data }) {
  const post = data.markdownRemark
  return (
    <Layout>
      <div>
        <h1>{post.frontmatter.title}</h1>
        <div dangerouslySetInnerHTML={{ __html: post.html }} />
      </div>
    </Layout>
  )
}

export const query = graphql`
  query($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
      }
    }
  }
`

うんうん。graphqlでマークダウンのhtml情報を取得してsrc/templates/blog-post.jsに書き込む感じか。 2020-09-06_03h15_57.jpg 出来た! そしてsrc/pages/index.jsを修正

import React from "react"
import { css } from "@emotion/core"
import { Link, graphql } from "gatsby"←ここ修正
import { rhythm } from "../utils/typography"
import Layout from "../components/layout"

export default function Home({ data }) {
  return (
    <Layout>
      <div>
        <h1
          css={css`
            display: inline-block;
            border-bottom: 1px solid;
          `}
        >
          Amazing Pandas Eating Things
        </h1>
        <h4>{data.allMarkdownRemark.totalCount} Posts</h4>
        {data.allMarkdownRemark.edges.map(({ node }) => (
          <div key={node.id}>
            ↓ここから
            <Link
              to={node.fields.slug}
              css={css`
                text-decoration: none;
                color: inherit;
              `}
            >
            ↑ここまで修正
              <h3
                css={css`
                  margin-bottom: ${rhythm(1 / 4)};
                `}
              >
                {node.frontmatter.title}{" "}
                <span
                  css={css`
                    color: #555;
                  `}
                >
                  — {node.frontmatter.date}
                </span>
              </h3>
              <p>{node.excerpt}</p>
            </Link>←ここ修正
          </div>
        ))}
      </div>
    </Layout>
  )
}

export const query = graphql`
  query {
    allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
      totalCount
      edges {
        node {
          id
          frontmatter {
            title
            date(formatString: "DD MMMM, YYYY")
          }
          ↓ここから
          fields {
            slug
          }
          ↑ここまで修正
          excerpt
        }
      }
    }
  }
`

再起動 index.jsからpostにアクセスできるようになった! チュートリアルはここまでかな。

これ、src/pages内にmdファイルあるのが気になるから移動できないかしら? src/mdディレクトリ作成し、mdファイルを移動 2020-09-06_03h26_25.jpg 再起動 2020-09-06_03h27_21.jpg うん、問題ないね! 今回はここまで。

ありがとうございました。


SaitoSystemService

埼玉在住のフリーランスSEです。 技術ブログや作品をここで紹介していきます。 よろしくお願いします。

Written by 齋藤 渓
埼玉在住のフリーランスSEです。技術ブログや作品をここで紹介していきます。よろしくお願いします。
Contact:
© 2020, 齋藤システムサービス by Gatsby