🌟

useSWRでデータフェッチするコンポーネントでSusponseを使うとエラーが出る

2024/06/14に公開

Next.jsでuseSWRでデータフェッチするコンポーネントでSusponseを使うと下記のエラーが出ました。

Error: Fallback data is required when using suspense in SSR.

サーバーサイドレンダリング(SSR)を行う際に、useSWRを使うと発生するエラーで、Suspenseがデータを待っている間に表示するフォールバックデータが必要であるためです。

回避策1. SSRしないようにする

SSR時に発生するエラーなのでコンポーネントをSSRすれば回避できます。

dynamic関数を使ってコンポーネントをインポートする際にssrオプションをfalse指定すればSSRされません。

import dynamic from 'next/dynamic';
import React, { Suspense } from 'react';

const DataComponent = dynamic(() => import('./DataComponent'), {
  ssr: false
});

export default function Page() {
  return <div>
    <Suspense fallback={<div>Loading...</div>}>
      <DataComponent />
    </Suspense>
  </div>
}

回避策2. useSWRでフォールバックデータを渡す

useSWRのドキュメントでは下記のように記載されています。

サスペンスモードをサーバサイド(Next.js によるプリレンダリングを含む)で使う場合、fallbackData や fallback により初期データが提供されている必要があります。

https://swr.vercel.app/ja/docs/suspense#server-side-rendering

このような感じでフォールバックデータをサーバサイドから渡してやるとOK

 export async function getStaticProps () {
  // `getStaticProps` はサーバーサイドで実行されます
  const article = await getArticleFromAPI()
  return {
    props: {
      fallback: {
        '/api/article': article
      }
    }
  }
}
 
function Article() {
  // `data` は `fallback` 内にあるため常に利用可能です
  const { data } = useSWR('/api/article', fetcher, {
    suspense: true,
    fallbackData: {}
  })
  return <h1>{data.title}</h1>
}
 
export default function Page({ fallback }) {
  // `SWRConfig` 内の SWR フックはそれらの値を使用します
  return (
    <SWRConfig value={{ fallback }}>
      <Article />
    </SWRConfig>
  )
}

またはuseSWRに渡す方法でも良いです。

const { data } = useSWR('/api/article', fetcher, {
  suspense: true,
  fallbackData: {}
})

しかし2だとSuspenseのfallbackが使えない…

fallbackDataの方が優先されてしまい肝心のSuspenseのfallbackが使えません。これは致命的です。
なので、1の方法で回避するのが良いでしょう。

下記の記事に詳しく説明されています。
https://zenn.dev/key5n/articles/06cd789d30b98c

Discussion