当サイトは、アフィリエイト広告を利用しています

【Gatsby】GraphQLの使い方

作成日:2022月10月15日
更新日:2023年12月27日

GatsbyにおけるGraphQLの役割や使い方についてまとめてみる Gatsbyでは各データソースからデータを取得する際はGraphQLを使う。
GraphQLを使うことで異なるサーバーやmicroCMS,ローカルから効率的にデータを取得できる。
このGraphQLには

  • pageQuery
  • staticQuery

があり、できることや使い方やに違いあるので整理していく

GraphQLって何?

GraphQLの前にGatsbyデータシステムの中心となる「ノード」について
簡単にまとめる。

ノードとは?

GatsbyではGatsbyに追加されるすべてのデータはノードを使用してモデル化される。
簡単に言い換えてみると

  • ローカルのMarkdownファイル
  • Contentful
  • WordPress

などのデータソースは全てGatsby上ではノードとして扱われる。
ちなみにノードの構造は下記のような感じになってる

node
interface Node {
id: string;
children?: Array<string>;
parent?: string;
fields: object;
internal: {
contentDigest: string;
mediaType?: string;
type: string;
owner: string;
fieldOwners: object;
content?: string;
description?: string;
};
[key: string]: unknown; // ...other fields specific to this type of node
}

ノードインターフェース

再度、GraphQLとは?

GraphQLはこのノードに対してクエリを投げてデータを取得することができる。
つまり、異なるデータソースでもGatsby上では全てノードとなっているので
GraphQLを使って一元的に扱うことができる。 ※ちょっと文章だけだと難しいので後でサンプルを載せます

プラグイン

Gatsbyには多くのプラグインがあり、サイトの用途に合わせて必要なプラグインを組み合わせて
使用していく必要がある。
プラグインには用途によって種類がかなりあるのでここではGraphQLでデータを取得する際に
使用するプラグインの役割をまとめる。

データ取得系のプラグインの役割

データ取得系のプラグインは例えば下記などがある。

  • gatsby-source-filesystem
  • gatsby-source-microcms
  • gatsby-source-contentful

これらはインストールすることでそれぞれのリソースにgraphQLでアクセスできるようになる
※プラグインはリソースをノードに変換してGatsbyからgraphQLでアクセスできるようにしている

gatsby-source-contentfulの場合

サンプルとしてgatsby-source-contentfulのイントール前と後を
GraphiQL(GraphQLのIDE)で確認してみるとcontentfulのデータが追加されていることがわかる。

追加前

2022-09-25-23-59-49

contentfulの項目がない

追加後

2022-09-26-01-06-50

allContentfulBlogPostというcontenfulのデータが増えている。

このように適宜、必要なプラグインを追加することで下記のようなことができるようになる。

  • markdownファイルを扱えるプラグインをインストールすれば、graphQLでmarkdownファイルのデータを取得できる
  • Contentfulのプラグインをインストールすれば、graphQLでContentfulデータを取得できる
  • gatsbyサイト自体からGraphQLでデータを取得できる

※実際に行う場合は、プラグインのインストールに加えて、gatsby-config.jsで設定を書く必要がある。

Gatsbyでcontentfulのデータを扱う方法については下記に記事でまとめています。

GraphQLの種類

Gatsbyで使用するGraphQLは大きく分ける

  • pageQuery
  • staticQuery

の2種類がある。

pageQuery

pageQueryはpageとなるコンポーネントでのみ使用できるGraphQL。
具体的には「pages/ディレクトリ」と「templateディレクトリ」配下にあるファイル内で
使用することができる。

pages/ディレクトリ配下で使うpageQuery

仮の当ブログの記事のタイトルを一覧で表示する下記のようなページを
pageQueryを使って作成してみる

記事タイトル一覧ページ

2022-10-02-02-19-23

タイトルを羅列しただけのページ!!

GraphiQLでpageQueryを作成する

上記ページに表示させるタイトルをcontentfulから取得するGraphQLを作成する

2022-10-13-00-27-30

GraphiQLでは項目を選んでいくだけでGraphQLを作成できる

「pages/ディレクトリ」配下のファイルで使う

作成したGraphQLを使ってindex.jsxを作成する

GraphiQLの「Code Exporter」を使えばテンプレートを自動生成してくれる

2022-10-13-00-31-57

自動生成したソースを書き換えてタイトル一覧を表示するようにする

pages/index.jsx
import * as React from "react"
import { Link, graphql } from "gatsby"
const BlogIndex = ({ data }) => {
const nodeList = data.allContentfulBlogPost.edges
return (
// 取得したタイトルを一覧で表示する
<div>
{nodeList.map(({ node }) => {
return (
<div>
<Link to={node.slug}>{node.title}</Link>
</div>
)
})}
</div>
)
}
export default BlogIndex
// 記事のタイトルとslugを取得
export const pageQuery = graphql`
query {
allContentfulBlogPost {
edges {
node {
title
slug
}
}
}
}
`
  • pageQueryはコンポーネントの外に書く。
  • pageQueryの取得結果は「data」に格納されコンポーネントのpropsに渡される
    ※上記では分割代入でdataを取得している

「template/ディレクトリ」配下のファイルで使う

pageQueryはbuild時に静的ページ生成を行う際、 template/ディレクトリ配下のファイルでも使用できる。
pages/ディレクトリ配下で使うpageQueryとの違いは

  • gatsby-node.jsから引数を受け取ることができる

こと。

静的ページ生成時のpageQueryの使用例

静的ページを作成する時のサンプルを作ってみる

gatsby-node.js
const path = require(`path`)
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
// contentful記事のkeyを取得
const contentfulAirticleResult = await graphql(`
query airticleQuery {
allContentfulBlogPost {
edges {
node {
slug
}
}
}
}
`)
const contentfulAirticle =
contentfulAirticleResult.data.allContentfulBlogPost.edges
//記事数分ループして記事ページを作成する
contentfulAirticle.forEach(({ node }) => {
createPage({
path: `${node.slug}/`, //記事ページのurl
component: path.resolve(`./src/templates/contentfulPost.jsx`), //記事ページ作成のtemplateコンポーネント
//templateコンポーネントに渡す引数
context: {
slug: node.slug,
},
})
})
}
  • contextに引数にする値を設定する
    ※今回はslugを引数にする
template/contentfulPost.jsx
import React from "react"
import { graphql } from "gatsby"
import MDXConvert from "../components/mdxConvert"
const ContentfulPost = ({ pageContext,data }) => {
const post = data.allContentfulBlogPost.edges[0].node
const { body } = post
// MDX形式の記事データをMDXConvertでhtmlに変換する
return <MDXConvert>{body.childMdx.body}</MDXConvert>
}
export default ContentfulPost
// gatsby-node.jsのcreatePageから渡されたslugを元にGraphQLで記事を取得する
export const query = graphql`
query Query($slug: String!) {
allContentfulBlogPost(filter: { slug: { eq: $slug } }) {
edges {
node {
body {
childMdx {
body
}
}
}
}
}
}
`
  • GraphQLでgatsby-node.jsで引数に設定したslugを使って記事をフィルタリングして取得している
  • gatsby-node.jsで引数に設定したslugをコンポーネントで使いたい場合はpageContextで受け取ることもできる

※MDX形式でcontentful記事を表示する場合のソースをサンプルにしています

pageQueryをまとめると

  • pagesディレクトリ配下のファイルまたは、templateディレクトリ配下のファイルでのみ使用できる
  • 静的ページ生成時(templateディレクトリ配下のファイル)では引数をとれる。
  • pageQueryはコンポーネントの外に書く。
  • pageQueryの取得結果は「data」に格納されコンポーネントのpropsに渡される

staticQuery

pageQueryに対してstaticQueryはあらゆるコンポーネントで使うことができる。 pagesディレクトリ配下やtemplateディレクトリ配下以外のコンポーネントでは
staticQueryを使ってデータを取得する。

staticQueryを使ってみる

pageQueryで作成した記事タイトル一覧ページの上にタグ一覧を
タグ一覧用コンポーネントを作って表示してみる

GraphiQLでstaticQueryを作成する

pageQueryを作成した時と同様にGraphiQLでGraphQLを作成する

2022-10-16-02-36-39

  • contentfulからタグのタイトルを取得する
  • ソースコードはCode ExporterでStaticQuery hookを選択して生成

タグ一覧表用コンポーネントを作る

GraphiQLで作成したstaticQueryを使って作成する

component/allTag.jsx
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
const Alltags = () => {
//staticQuery
const data = useStaticQuery(graphql`
{
allContentfulTags {
edges {
node {
title
}
}
}
}
`)
const nodeList = data.allContentfulTags.edges
return (
// 取得したタグタイトルを一覧で表示する
<div>
{nodeList.map(({ node }) => {
return (
<div>
<button>{node.title}</button>
</div>
)
})}
</div>
)
}
export default Alltags
  • staticQueryはコンポーネントの中で使う

タグ一覧表用コンポーネントを一覧画面に追加

タグ一覧表用コンポーネントを追加する

pages/index.jsx
import * as React from "react"
import { Link, graphql } from "gatsby"
import Alltags from "../components/allTags"
const BlogIndex = ({ data }) => {
const nodeList = data.allContentfulBlogPost.edges
return (
// 取得したタイトルを一覧で表示する
<div>
<Alltags />
{nodeList.map(({ node }) => {
return (
<div>
<Link to={node.slug}>{node.title}</Link>
</div>
)
})}
</div>
)
}
export default BlogIndex
// 記事のタイトルとslugを取得
export const pageQuery = graphql`
query {
allContentfulBlogPost {
edges {
node {
title
slug
}
}
}
}
`

Gatsbyを起動して画面を表示してみる

2022-10-16-02-51-46

タグ一覧が表示されている

staticQueryをまとめると

  • staticQueryはコンポーネントの中に書く。
  • staticQueryはどのコンポーネントでも使用できる
  • staticQueryには引数を渡すことはできない

まとめ

GatsbyにおけるGraphQLの使い方とGraphQLの種類(pageQueryとstaticQuery)について
忘れないようにまとめてみた。
staticQueryはどこでも使えるのはいいが、引数が渡せないのでデータ取得を動的に行うことが
できないのがちょっと残念。

参考書籍

Gatsbyを使ってサイト開発するにに読んだ本です。
GraphQLの基本的な使い方についても参考にしました。

参考

新着記事

top