Next.jsのgetStaticPaths APIのfallbackを理解する

執筆日: 2021-08-25

概要

例えば、Next.jsでブログページを作成することになったとします。
その際に使用するAPIとして、ビルド時にデータを取得するgetStaticPropsと動的ページを作成するgetStaticPathsが有効です。

さて、今回はgetStaticPathsAPIのfallback指定に焦点を当てます。自身の問題を例として、理解を深めていきます。

問題点

中の人がmicroCMSを使用し、記事詳細ページを作成しようとしている場面です。

[id].tsx
export const getStaticPaths = async () => {
  const data = await client.get<Posts>({ endpoint: 'posts' })
  const paths = data.contents.map((x) => `/post/${x.id}`)
  return { paths, fallback: true }
}

export const getStaticProps = async (context) => {
  const id = context.params.id
  const post = await client.get<Post>({ endpoint: 'posts', contentId: id })

  return {
    props: {
      post,
    },
  }
}

const PostId: NextPage<InferGetStaticProps<typeof getStaticProps>> = ({ post }) => {
  return (
    <div className="py-36px container container--tight">
      <article key={post.id}>
        <figure className="mb-16px">
          <Image src={post.thumbnail.url} layout="responsive" width={384} height={216} alt="" />
        </figure>
        <time className="text-gray-600 text-12px mb-6px inline-block" dateTime={format(new Date(post.publishedAt), 'yyyy-MM-dd')}>{format(new Date(post.publishedAt), 'yyyy/MM/dd')}</time>
        <h3 className="font-bold">{post.title}</h3>
      </article>
    </div>
  )
}

export default PostId

開発環境では問題なく表示されていましたが、ビルドコマンドで以下のようなエラーが発生しました。
thumbnail is not undefined.

開発ではうまく表示できていたのに、ビルド時にエラーがでるのはなぜでしょうか。

原因

fallback: trueが問題だったようです。

fallback指定の内容ですが、3つの値をとります。

  • false: getStaticPathsによって返されないパスは404ページになる。
  • true: ビルド時に生成されていないパスは404ページにならず、フォールバックページが提供される。
    フォールバックページには空のオブジェクトがpropsで渡される。
    その後、getStaticPropsが呼び出され、再レンダリングされる。
  • blocking: HTMLが生成されるのを待ち、レンダリングされる。先にgetStaticPropsが行われる。

つまり、今回の例だと以下のことが言えます。

fallback: true にしたことでフォールバックページが作られる。空のオブジェクトが渡ってくるが中身が存在しないのでエラーが発生した。

解決策

router.isFallback

フォールバックページがレンダリングされると、router.isFallbackがtrueになるので、利用します。

import { useRouter } from 'next/router'

...省略
const router = useRouter()
if (router.isFallback) {
  return <div>Loading...</div>
}
...省略

‘blocking’指定

これが一番簡単に解決できます。
HTMLが生成されるまで待つことで、取得データをpropsに渡すことができます。

export const getStaticPaths = async () => {
  const data = await client.get<Posts>({ endpoint: 'posts' })
  const paths = data.contents.map((x) => `/post/${x.id}`)
  return { paths, fallback: 'blocking' }
}

結論

Next.jsのgetStaticProps APIにおけるfallbackとは何か、読者の理解の一助になれば幸いです。

わからない時はドキュメントが一番なので、確認してみてください。

参照

Next.js -The fallback key

運営について

Natural Tearoomはシステム開発会社フロントエンドエンジニアがんちゃんが運営するメディアです。
フロントエンド技術を中心に発信しています。

· プライバシーポリシー

SNS

© 2021 天然珈琲店