GatsbyのデータレイヤーからgraphQLでデータを取得する
はじめに
Gatsbyでブログを書くためには、1ページずつHTMLを書くわけにもいかないので、記事を書いたデータベースからデータを取得してコンポーネントに組み込む必要がある。
Gatsbyではデータの取得にGraphQLを利用する。
GraphQLでのデータ取得方法の基礎的なやり方をメモする。
参考
システム構成図:GatsbyブログをGatsby Cloudで公開してみた - エンジニアを目指す日常ブログ
GraphQLとは:tomiko0404.hatenablog.com
この記事のゴール
- GraphQLのクエリ作成方法と、結果の利用方法を理解する。
gatasby-config.js
で設定したsiteMetadata
のデータをGraphQLで取得し、コンポーネントに反映する。
前回の記事
前提
- gatsby-starter-blogスターターキットを利用したgatsbyブログを立ち上げ済
- Vagrantを開発環境として利用
- Gatsby Cloudで公開済(今回は利用しないので、なくても可)
- はじめに
- Gatsbyデータ管理のしくみ
- GraphQLでのデータ取得
- GraphiQLを活用した要求電文の生成
- 【参考】useStaticQueryとgraphqlどちらを使うか
- 注意:graphqlのクエリは、1つのコンポーネントに1つしか入れられない
- おわりに
- 関連記事
Gatsbyデータ管理のしくみ
以下の図のように、まず「ソースプラグイン」と呼ばれるプラグインを利用し、データを「データレイヤー」に取り込む。データレイヤーのデータにGraphQL APIでアクセスし、コンポーネント側で利用する。
ソースプラグイン
以下のサイトでgatsby-souce-
で検索するとソースプラグインが出てくる。
https://www.gatsbyjs.com/pluginswww.gatsbyjs.com
gatsby-source-filesystem
gatsby-source-contentful
gatsby-source-graphql
等がある。例えば、ヘッドレスCMSの「Contentful」からデータを取得する場合にはgatsby-source-contentful
を使うのが良い。
ソースプラグインを利用したデータの取得方法は後日記載
siteMetadata
オブジェクトの取得
gatsby-config.js
でmodule.exports
しているデータは、ソースプラグインを利用しなくても自動的にGatasbyのデータレイヤにプルされている。
gatsby-config.js
で設定したsiteMetadata
オブジェクトは、GatsbyデータレイヤーからGraphQL APIで取得できる状態になっているので、試しに取得してみる。
GraphQLでのデータ取得
useStaticQuery
関数を利用してデータ取得
Aboutページに、siteMetadata
のtitle
を取得して追加してみる。
情報の取得には、今回useStaticQuery
を使う。
import { useStaticQuery, graphql } from 'gatsby';
でのインポートと、
const data = useStaticQuery(graphql` // 要求電文 `)
が必要である。
取得したデータは、通常のオブジェクトと同様
<p>{data.site.siteMetadata.title}</p>
のように利用できる。
src/pages/about.js
import { useStaticQuery, graphql } from 'gatsby'; import * as React from 'react' import MyLayout from '../components/myLayout'; const About = () => { const data = useStaticQuery(graphql` query { site { siteMetadata { title } } } `) console.log(data) return ( <MyLayout pageTitle="このサイトについて"> <p>{data.site.siteMetadata.title}</p> <p>ayです。Gatsbyを利用し作成しています。</p> <p>お問い合わせはこちら 03-xxxx-xxxx</p> </MyLayout> ) } export default About;
Aboutページに、data.site.siteMetadata.title
を表示することができた。
graphql
関数を利用したデータ取得
インポート文は以下。
import { graphql } from 'gatsby';
クエリの書き方は以下のようになる。
export const query = graphql` //要求電文 `
このように書くと、自動的にコンポーネントのprops.data
に値が渡される。
詳細は、以下の記事を参照。
GraphiQLを活用した要求電文の生成
要求電文の生成方法にくせがあるので、GraphiQLというツールを利用する。
こちらも参照:GraphQLって何? - エンジニアを目指す日常ブログ
Gatsbyでは、gatsby develop
を実行して、
http:localhost:8000/___graphiql
にアクセスすると、GraphiQLでGraphQLデータレイヤーにあるフィールドに対する要求電文と応答電文をテストできる。
以下のように、Gatsbyデータレイヤーで利用できる、クエリのルートフィールドが一覧になっている。
右側のDoc
で、今回使うクエリのsite
を確認すると、
- 引数
buildTime: DateQueryOperatorInput children: NodeFilterListInput host: StringQueryOperatorInput id: StringQueryOperatorInput internal: InternalFilterInput jsxRuntime: StringQueryOperatorInput parent: NodeFilterInput pathPrefix: StringQueryOperatorInput polyfill: BooleanQueryOperatorInput port: IntQueryOperatorInput siteMetadata: SiteSiteMetadataFilterInput
- 応答値の型
Site
となっている。
Site
型の構成は、
buildTime( difference: String formatString: String fromNow: Boolean locale: String ): Date siteMetadata: SiteSiteMetadata port: Int host: String polyfill: Boolean pathPrefix: String jsxRuntime: String id: ID! parent: Node children: [Node!]! internal: Internal!
となっている。
siteMetadata: SiteSiteMetadata
のSiteSiteMetadata
型の構成は
title: String description: String author: Author siteUrl: String social: Social
となる。
これをふまえて、site
ツリーを開いていってtitle
にチェックを付けると要求電文が出来上がる。
応答電文としてtitle
が取得できていることがわかる。
title
には、紫色と青色が2つあるが、紫色のほうは絞り込み条件を設定する際などに使用するものなので、今回は青色にチェックを入れた。
ここで作成した要求電文には、MyQuery
という名前がついているが、コンポーネント内で利用するときはその部分は削除することに注意する。
【参考】useStaticQuery
とgraphql
どちらを使うか
gatsby-starter-blogスターターキットのindex.js
には既にGraphQLのクエリが存在するが、そちらではuseStaticQuery
を利用していない。
src/pages/index.js
export const pageQuery = graphql` query { site { siteMetadata { title } } allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) { nodes { excerpt fields { slug } frontmatter { date(formatString: "MMMM DD, YYYY") title description } } } } `
以下のサイトに解説があった。
useStaticQuery
を使わない場合のクエリを「ページクエリ」と呼ぶそうで、useStaticQuery
はコンポーネントの中に書くのに対し、ページクエリはコンポーネントの外に書く。
また、ページクエリは、単独でページになるコンポーネント(/pages
配下にあるようなコンポーネント)でしか使えないという制約があるらしい。
注意:graphqlのクエリは、1つのコンポーネントに1つしか入れられない
graphqlのクエリは、1つのコンポーネントに1つしか入れられないようだ。
index.js
で同じことを実施すると、エラーになってしまった。
利用しているgatsby-starter-blogスターターキットでは、index.js
上に既に完成されたGraphQLのクエリが存在するため、エラーになってしまった。
ERROR #85910 GRAPHQL Multiple "root" queries found: "(クエリ名1)" and "(クエリ名2)". Only the first ("(クエリ名2)") will be registered. Instead of: 1 | query (クエリ名2) { 2 | site { 3 | #... 4 | } 5 | } 6 | 7 | query (クエリ名1) { 8 | site { 9 | #... 10 | } 11 | } Do: 1 | query (クエリ名1)(クエリ名2) { 2 | site { 3 | #... 4 | } 5 | site { 6 | #... 7 | } 8 | } This can happen when you use two page/static queries in one file. Please combine those into one query. If you're defining multiple components (each with a static query) in one file, you'll need to move each component to its own file.
おわりに
Gatsbyのデータレイヤーに存在するデータをGraphQL APIで取得することができた。