❗問題#
最近勇哥が AI 対話アプリケーションを作成する過程で、URL からパラメータを取得するために useSearchParams 方法を使用しました。development モードではすべて正常でしたが、build 時にエラーが発生しました:
⨯ useSearchParams() should be wrapped in a suspense boundary at page "/".
❓原因#
公式の説明は次のとおりです:
Suspense 境界がない状態で useSearchParams () を使用して検索パラメータを読み取ると、ページ全体がクライアントレンダリングに入ります。これにより、クライアントの JavaScript が読み込まれるまでページが空白のままになる可能性があります。
勇哥は静的レンダリングを使用しているため、useSearchParams
方法はURLSearchParams
インターフェースの読み取り専用インターフェースを返します。そして、URLSearchParams
はブラウザに依存しているため、window オブジェクトが読み込まれるまで待つ必要があります。
✔解決方法#
公式の推奨解決策は非常に簡単です:useSearchParams () の呼び出しがSuspense
でラップされていることを確認してください。
変更前、勇哥の page.tsx ファイルは次のようになっていました:
'use client';
...
import { useRouter, useSearchParams } from 'next/navigation'
import { SidebarProvider, SidebarInset } from "@/components/ui/sidebar"
...
// メインページコンポーネント
export default function Page() {
const router = useRouter()
const urlParams = useSearchParams()
// ... その他の状態とロジック
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
...
</SidebarInset>
</SidebarProvider>
);
}
変更後:
'use client';
import { Suspense } from "react"
import { useRouter, useSearchParams } from 'next/navigation'
import { SidebarProvider, SidebarInset } from "@/components/ui/sidebar"
// すべてのクライアントロジックを処理するラッピングコンポーネントを新規作成
function ChatPageContent() {
// ... 元の状態とロジック
const router = useRouter()
const urlParams = useSearchParams()
// ... その他の状態とロジック
return (
<SidebarProvider>
<AppSidebar />
<SidebarInset>
...
</SidebarInset>
</SidebarProvider>
);
}
}
// メインページコンポーネント
export default function Page() {
// ラッピングコンポーネントの外側に<Suspense />を追加
return (
<Suspense fallback={<div>チャットを読み込んでいます...</div>}>
<ChatPageContent />
</Suspense>
);
}
useSearchParams
を使用するクライアントコンポーネントを<Suspense/>
でラップします。この場合、ルーティングの一部は静的にレンダリングされ、useSearchParams
を使用する動的部分はクライアントで window オブジェクトが利用可能になった後にレンダリングされます。