勇哥

勇哥开发之路

I build things on web.

Next.js 踩坑之 useSearchParams()

❗問題#

最近勇哥在做 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 對象可用後再渲染。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。