Contentful + Netlify + Gatsby で連携しているさいに childMarkdownRemark が null になる Error の直し方
Tweetこのサイトは Gatsby + Netlify + Gatsby で運用していて、開発体験もページ遷移速度も SEO も優れていて、非常に気に入っているのですが、今日そこそこハマりその解決策がわかったので、メモします。
Contentful から取得した content の childMarkdownRemark が存在しない場合のエラー処理を追加すること
Contentful にマークダウンでブログコンテンツを保持して、変更があった場合には Netlify に hook をして、Netlify で運用している Gatsby が静的サイトをビルドし直す。これが Contentful + Netlify + Gatsby を連携している場合の基本的な運用ですが、稀に childMarkdownRemark もしくは content がない記事が発生する場合があります。その場合は当然ですが null
の場合のハンドリングをします。
具体的には以下のような箇所でおきます。
<div
className="post-content"
dangerouslySetInnerHTML={{
__html: post.content.childMarkdownRemark.html,
}}
/>
私の場合 childMarkdownRemark is null
というエラーが出ていました。
Contentful から取得してきたデータのうち、childMarkdownRemark.html
を Gatsby でレンダリングする際に、これが null
のためにエラーが出ているわけです。
null
の場合だけ childMarkdownRemark.html
を使わないように適当な内容を返せばいいです。
以下実際のこのブログのソースです。
import React from 'react'
import { graphql, Link } from 'gatsby'
import Layout from '../components/layout'
import SwitchEnglish from 'src/components/SwitchEnglish'
export default ({ data }) => {
const post = data.contentfulBlogPost
const translatedMode = post.tags.some(
o => o === 'Translated-Text' || o === 'Translated Text'
)
const { content } = post // この値が null になることがわかったので
if(!content) {
console.log(post)
return <div>Error</div> // 例外の場合は適当なものを返す
}
return (
<Layout description={post.description} title={post.title}>
<div className="post">
<div className="title-wrapper">
<h1 className="post-title">{post.title}</h1>
<a
target="_blank"
rel="noopener noreferrer"
href={`https://twitter.com/intent/tweet?text=${
post.title
}%0a&hashtags=UncleJavascript&url=https://uncle-javascript.com/${
post.slug
}/&via=better_than_i_w`}
className="tweet"
>
Tweet
</a>
</div>
<div className="post-ui-wrapper">
<div className="post-ui-item-wrapper">
{post.tags.map(o => (
<Link key={o} to={o} className="post-ui-item">{o}</Link>
))}
</div>
<SwitchEnglish translatedMode={translatedMode} />
</div>
<div
className="post-content"
dangerouslySetInnerHTML={{
__html: post.content.childMarkdownRemark.html,
}}
/>
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
contentfulBlogPost(slug: { eq: $slug }) {
id
title
description
slug
tags
content {
childMarkdownRemark {
html
}
id
content
}
createdAt
}
}
`
いつおきるのか
完全に原因は特定できていないのですが、おそらく Contentful の記事更新の hook で netlify が再ビルドをしてエラーが出現した場合で、かつ同じタイミングで記事を増やした時ではないかなと思っています。
ただし、一旦 netlify でのビルドが正常化された後には、content が null になる記事は存在しなくなりました。本当に一時的に起こるようです。
以下根拠のない推測ですが、Contentful の記事更新 => hook => Netlify の通知だけではなく、Netlify のビルド終了 => Contentful の通知もあって、それによって Build する内容を規定しているのではないでしょうか。
何にせよ、エラーがおきている箇所で値が存在するかどうかをチェックして、例外処理するという一般的な開発フローで解決できてよかったです。