2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Next.js】accessed outside of <Suspense>エラーが発生した原因とその対策例

2
Posted at

こんにちは。

個人開発で、Next.jsを用いたブログサイトの詳細ページを作成していた際に表題のようなエラーが発生しました。

その原因と対策方法について備忘録代わりに記載いたします。

発生したエラーとそれを引き起こしたコード

Next.jsで、ブログサイトの詳細ページ用コードとして以下のようなコードを記載していました。

[id]/page/tsx
'use cache';

type Params = {
  id: string;
}

export default async function page({ params }: { params: Promise<Params> }) {
  const { id } = await params;

  // 以下はidを取得するテスト。実際は他の値もprops経由で取得する予定だった

  return (
    <>
      <div>
        <p>テスト{id}</p>
      </div>
    </>
  )
} 

このコードでnpm run devで[id]付きページを参照したところ、以下のようなエラーが発生しました。

Error: Route "/[id]": Uncached data or connection() was accessed outside of <Suspense>. This delays the entire page from rendering, resulting in a slow user experience. Learn more: https://nextjs.org/docs/messages/blocking-route

Error: ルート "/[id]": cookies()headers()params、または searchParams などのランタイムデータが <Suspense> の外でアクセスされました。これによりページ全体のレンダリングが遅延し、ユーザーエクスペリエンスが低下します。

エラー内容の把握・公式ドキュメントの確認

このようなケースではまずLearn moreで記載されている公式ドキュメントを見るのが第一なので、公式ドキュメントを確認します。

原因となるWhy This Error Occurredの箇所を確認します。
※原文は全て英語なためChatGPT Translateで和訳したものを引用として記載いたします。

cacheComponents 機能が有効になっている場合、Next.js は、すべてのユーザーリクエストでアクセスする必要があるデータを await するコンポーネントの周囲に、親 Suspense 境界があることを想定します。この要件の目的は、Next.js がこのデータへのアクセスとレンダリング中に、有用なフォールバックを提供できるようにすることです。
これは通常、親 Suspense 境界なしでコンポーネントが次のいずれかを行った場合に発生します。
・Page または Layout で params を await する、または Page で searchParams を await する
・cookies()、headers()、または connection() を呼び出す
・"use cache" でキャッシュされていないデータを取得する
参照元:https://nextjs.org/docs/messages/blocking-route#why-this-error-occurred

今回のケースだとcacheComponents機能が有効かつ<Suspense>境界がない状態で"use cache"を使っていることが原因のようでした。

対策例

"use cache"ページの一部は静的にキャッシュさせ、別の部分は動的にレンダリングさせるためのものです。

今回実装していたコードはCMSの詳細ページ=そもそも動的にレンダリングさせる必要性が薄いページだったので、「cacheComponents機能およびuse cacheを使わない」方向で対策しました。

next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // cacheComponents: true を削除する
  - cacheComponents: true,
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.microcms-assets.io'
      }
    ]
  }
};

export default nextConfig;
[id]/page.tsx
// 'use cache' を削除する
- 'use cache';

type Params = {
  id: string;
}

export default async function page({ params }: { params: Promise<Params> }) {
  const { id } = await params;

  return (
    <>
      <div>
        <p>テスト{id}</p>
      </div>
    </>
  )
} 

上記のようにcacheComponentsの設定項目を削除し、'use cache'も削除することでエラーが発生せずに動くようになりました。

役割的にServer Component=静的ページで問題ない箇所だったのでこれでも問題なく機能しました。

最後に

ここまで読んでいただきありがとうございました。

'use cache'はつい多用したくなりますが、ページやコンポーネントの役割を考慮して使うことが大事であることを学びました。

参考資料

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?