GatsbyでHello, worldからサイトを作ってみる(3) データの取得と一覧ページの作成

2019.6.1 12:00

概要

ポートフォリオの一覧ページを、ポートフォリオが増えるごとにいちいち手直ししていては、とても大変である。なので、一箇所でデータを定義したら、それに沿っていろんなページが自動的に構成されるようにできれば便利である。

そこで、今回はその第一歩として一覧ページが自動的に構成されるようにしたい。

必要なプラグインのインストール

Gatsbyには標準でファイルを読み込む仕組みがないため、必要なプラグインを導入する。今回導入するプラグインはソースプラグインとトランスフォーマプラグインと呼ばれているものである。

$ yarn add gatsby-source-filesystem gatsby-transformer-yaml

ソースプラグイン

gatsby-source-で始まるプラグインはソースプラグインと呼ばれている。例えば、Webサービスなのか、データベース上なのか、ローカルファイルなのか。どこにあるデータなのかによって取得の方法が変わってくるが、すべてをGatsbyがサポートしようとすると、複雑な仕組みが必要になり、作る側も使う側もとても大変なので、必要に応じて必要なものを追加する仕組みになっている。

3-1

今回はローカルファイル上のファイルを取得するので、gatsby-source-filesystemを使う。

トランスフォーマプラグイン

gatsby-transformer-で始まるプラグインはトランスフォーマプラグインと呼ばれている。例えば、JSONなのか、YAMLなのか、Markdownなのか。データがどんな形をしているのかによって解釈の方法が変わってくるが、すべてをGatsbyがサポートしようとすると、複雑な仕組みが必要になり、作る側も使う側もとても大変なので、必要に応じて必要なものを追加する仕組みになっている。

3-2

今回はYAMLのファイルを取得するので、gatsby-transformer-yamlを使う。

設定

プラグインの設定は、プロジェクトフォルダの中にgatsby-config.jsというファイルを配置することで行う。まずは下記の通りファイルを作成する。

gatsby-config.js
module.exports = {
  plugins: [ // pluginに関する設定はここで
    `gatsby-transformer-yaml`, // オプションがないときは文字列で良い
    { // オプションがあるときはオブジェクトで
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/portfolio/`, // ここの中のファイルを読み込む
      },
    },
  ],
};

データの作成

次に、プロジェクトフォルダの中にportfolioフォルダを作成し、その中にデータファイルを作成する。

portfolio/test1.yaml
title: test 1
description: これはテストです。
portfolio/test2.yaml
title: test 2
description: | 
  これはテストです。
  これはテストです。

ここまでできたらWebブラウザから http://localhost:8000/___graphql にアクセスしてみよう。

というのも、GatsbyはGraphQLと呼ばれるデータ取得用の言語を使った検索を行える仕組みを持っており、この仕組みでページの表示に必要なデータを取得している。Gatsbyはまた、Web上からGreaphQLでのデータ取得を試せるサイトを提供してくれている。

下記の通り、クエリを左側に入力してみよう。

{
  allPortfolioYaml { # gatsby-transformer-yamlならallXxxYamlという名前になる、Xxxはフォルダの名前(今回はPortfolio)
    edges { # GraphQLのルール
      node { # GraphQLのルール
        id # Gatsbyがidをつけてくれている
        title # yamlのキー名
        description # yamlのキー名
      }
    }
  }
}

再生ボタンのようなものを押すと、右側に下記の通りデータが出力される。つまり、先程導入したプラグインによりファイルの読み込みが自動的に行われ、検索可能になったことが分かる。

3-3

ページへのデータ投入

では、いよいよこのデータを使ってページを表示してみる。 前回のソースコードを修正していく。 なお、適宜、コメントで補足する。

src/pages/index.js
  import React from "react"
  import Layout from "../components/layout"
  import ItemList from "../components/item-list"
+ import { graphql } from "gatsby"

  export default ({ data /* クエリの結果はdataという名前で引数として受け取れる */ }) => (
    <Layout>
-     <ItemList />
+     <ItemList data={data} />
    </Layout>
  )

  /*
   * 1. graphqlに続けて``で囲った部分にクエリを書く
   * 2. その定数をexportする
   * とGatsbyで検索してくれる
   */
+ export const query = graphql`
+ query {
+   allPortfolioYaml {
+     edges {
+       node {
+         id
+         title
+         description
+       }
+     }
+   }
+ }
+ `
src/component/item-list.js
  import React from "react"

  import Item from "./item"

  import styles from "./item-list.module.css"

  export default () => (
    <div className={styles.container}>
-     <Item id={1} title="item 1" description="description 1" />
-     <Item id={2} title="item 2" description="description 2" />
+     {
+       data.allPortfolioYaml.edges.map(({ node }) => {
+         return <Item key={node.id} id={node.id} title={node.title} description={node.description} />;
+       })
+     }
    </div>
  )
src/component/item.js
  import React from "react"
  import {Link} from "@reach/router";

  export default ({ id, title, description }) => (
    <Link to={`/detail?id=${id}`}>
      <div>
        <strong>{title}</strong>
      </div>
-     <div>
-       {description}
-     </div>
+     <div dangerouslySetInnerHTML={{ __html: description.replace("\n", "<br />")}}/>
    </Link>
  )

Next

次回はデータの条件付き取得と詳細ページの表示を行っていく。詳細ページも今回定義したデータから自動的に構成されるようにする。

gatsby