Gatsby.js スタティックサイトのチュートリアル Part 4
Gatsby.jsでMDXを使用したブログサイトを作成するチュートリアルのPart4です。今回はGraphQLでデータを取得する方法を確認します。gatsby-config.jsに記載したtitleを取得してLayoutコンポーネントに使用します。またSeoコンポーネントの土台を作成します。
GraphQL
Gatsbyではサイト内のすべてのデータがGraphQLデータレイヤー(data layer)で管理されています。GatsbyにビルドインされているGraphiQLインターフェイスを使用してデータを検索しクエリを作成することができます。開発用ローカルサーバーを起動してhttp://localhost:8000/___graphqlにアクセスするとGraphiQLインターフェイスを開くことができます。
GraphiQLはGraphQLクエリが問題ないかをテストするために使います。まず画面左のツールバーにある'Show GraphQL Explorer'ボタンを押してエクスプローラーを開きます。
エクスプローラーペインで取得したいデータを選択し、真ん中のペインの'Execute query'ボタンを押せば右のペインに取得したデータが返されます。
これで取得したいデータを取得できるクエリが作成できているかを確認できます。
画像のようにsiteMetadataのtitleを取得する場合は、エクスプローラーペインでsiteフィールドのドロップダウンを開き、青字のsiteMetadata内のtitleを選択すればOKです。ここで選択しているsiteMetadataがgatsby-config.js内に記述したsiteMetadataオブジェクトに相当します。
エクスプローラーペインの見方ですが、青字で表記されているものが実際に選択するフィールドで、ターコイズ色でコロンがついているものは引数です。なので上記のようにタイトルを取得する場合は青字で表記されているsite→siteMetadata→titleの順に選択します。
useStaticQueryでサイトタイトルを取得する
複数のページで再利用するための構成ブロックにGraphQLで取得したデータを使用する場合は、Gatsbyで定義されているuseStaticQueryファンクションを使用します。Layoutコンポーネントでデータを使用するためにlayout.jsを下記のように変更します。
src/components/layout.js
import * as React from 'react'
import { Link, useStaticQuery, graphql } from 'gatsby'
import {
container,
navLinks,
navLinkItem,
navLinkText
} from './layout.module.css'
const Layout = ({ pageTitle, children }) => {
const data = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
}
}
}
`)
return (
<div className={container}>
<header>{data.site.siteMetadata.title}</header>
<nav>
<ul className={navLinks}>
<li className={navLinkItem}>
<Link to="/" className={navLinkText}>Home</Link>
</li>
<li className={navLinkItem}>
<Link to="/blog" className={navLinkText}>Blog</Link>
</li>
<li className={navLinkItem}>
<Link to="/contact" className={navLinkText}>Contact</Link>
</li>
</ul>
</nav>
<main>
<h1>{pageTitle}</h1>
{children}
</main>
</div>
)
}
export default Layout
importでuseStaticQueryとgraphqlを追加で読み込みます。data変数を定義してGraphiQLで作成したクエリを使用してtitleを取得します。
なおGraphiQLでクエリを作成する際にはデフォルトでMyQueryという名前がついていますが、プロジェクト内でクエリ名が重複してしまうとエラーになるためクエリ名を削除して使用しています。各クエリに独自の名前をつけたほうがデバックには有用ですが、公式のチュートリアルでも無名のクエリを使用しているので、このチュートリアルでも踏襲します。
取得したtitleをheaderタグ内で使用しサイトタイトルを表示します。表示を確認してみます。
左上に'Gatsby Static Site Tutorial'と表示されています。GraphQLを使用してデータを取得する方法が確認できました。
CSSを調整しておきます。layout.module.cssを下記のように変更します。
src/components/layout.module.css
.container {
margin: auto;
max-width: 500px;
font-family: sans-serif;
}
.nav-links {
display: flex;
list-style: none;
padding-left: 0;
}
.nav-link-item {
padding-right: 2rem;
}
.nav-link-text {
color: black;
}
.site-title {
font-size: 3rem;
color: gray;
font-weight: 700;
}
変更したCSSをLayoutコンポーネントに反映させるために下記のように変更します。
src/components/layout.js
import * as React from 'react'
import { Link, useStaticQuery, graphql } from 'gatsby'
import {
container,
navLinks,
navLinkItem,
navLinkText,
siteTitle,
} from './layout.module.css'
const Layout = ({ pageTitle, children }) => {
const data = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
}
}
}
`)
return (
<div className={container}>
<header className={siteTitle}>{data.site.siteMetadata.title}</header>
<nav>
<ul className={navLinks}>
<li className={navLinkItem}>
<Link to="/" className={navLinkText}>Home</Link>
</li>
<li className={navLinkItem}>
<Link to="/blog" className={navLinkText}>Blog</Link>
</li>
<li className={navLinkItem}>
<Link to="/contact" className={navLinkText}>Contact</Link>
</li>
</ul>
</nav>
<main>
<h1>{pageTitle}</h1>
{children}
</main>
</div>
)
}
export default Layout
ブラウザをリロードして表示を確認しておきます。
useStaticQueryを使用してSeoコンポーネントを作成する
Layoutコンポーネントにサイトタイトルが追加できたので、次にGraphQLを使用して各ページのtitleタグを更新します。ここまでのチュートリアルでは Head API に下記のようにtitleタグを記載していました。
export const Head = () => <title>Home Page</title>
ページにあわせて'Home Page | Gatsby Static Site Tutorial'といった表示になるようにしていきます。
まずsrc/components内にseo.jsを下記のように作成します。
src/components/seo.js
import * as React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
const Seo = ({ title }) => {
const data = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
}
}
}
`)
return (
<title>{title} | {data.site.siteMetadata.title}</title>
)
}
export default Seo
作成したSeoコンポーネントを Head API に使用します。index.jsを下記のように変更します。
src/pages/index.js
import * as React from 'react'
import Layout from '../components/layout'
import { StaticImage } from 'gatsby-plugin-image'
import Seo from '../components/seo'
const IndexPage = () => {
return (
<Layout pageTitle="Home Page">
<p>I'm making this by following the Gatsby Tutorial.</p>
<StaticImage
alt="Sample Image 01"
src="../images/sample-image-01.png"
/>
</Layout>
)
}
export const Head = () => <Seo title="Home Page" />
export default IndexPage
importでSeoコンポーネントを読み込み、propsでタイトルを渡しています。ブラウザのタブを確認すると変更が確認できます。
同様にBlogページとContactページも変更します。まず、about.jsを下記のように変更します。
src/pages/about.js
import * as React from 'react'
import Layout from '../components/layout'
import Seo from '../components/seo'
const BlogPage = () => {
return (
<Layout pageTitle="Blog">
<p>Blog list goes here...</p>
</Layout>
)
}
export const Head = () => <Seo title="Blog" />
export default BlogPage
contact.jsを下記のように変更します。
import * as React from 'react'
import Layout from '../components/layout'
import Seo from '../components/seo'
const ContactPage = () => {
return (
<Layout pageTitle="Contact">
<p>Contact form goes here...</p>
</Layout>
)
}
export const Head = () => <Seo title="Contact" />
export default ContactPage
それぞれ表示を確認しておきます。
これでuseStaticQueryを使用したSeoコンポーネントを適用できました。Seoコンポーネントはおいおい情報を追加していきます。今回は以上です。