使用 useSearchParams 时缺少 Suspense 边界
此错误发生的原因
在没有 Suspense 边界的情况下通过 useSearchParams() 读取搜索参数将使整个页面选择客户端渲染。这可能导致您的页面在客户端 JavaScript 加载之前为空白。
可能的解决方法
根据您的意图,您有几个选择
- 要保持路由静态生成,请将调用 useSearchParams()的最小子树包装在Suspense中,例如,您可以将其用法移动到子客户端组件中,并使用Suspense包装该组件进行渲染。这保留了静态外壳并避免了完全的 CSR 回退。
- 要使路由动态渲染,请在服务器组件(例如页面或包装布局)中使用 connection函数。这会等待传入请求并排除下面的所有内容不进行预渲染。
app/page.tsx
import { connection } from 'next/server'
 
export default async function Page() {
  await connection()
  return <div>...</div>
}- 在 connectionAPI 可用之前,在服务器组件page.tsx或layout.tsx中设置export const dynamic = 'force-dynamic'会使路由选择按需渲染。请注意,在客户端组件('use client')page.tsx中设置dynamic无效。
app/layout.tsx
export const dynamic = 'force-dynamic'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return children
}- 或者,服务器组件页面可以将 searchParams值传递给客户端组件。在客户端组件中,您可以使用 React 的use()解包它(确保周围有Suspense边界)。请参阅 何时使用以及使用什么。
app/page.tsx
import { Suspense } from 'react'
import ClientSearch from './client-search'
 
export default function Page({
  searchParams,
}: {
  searchParams: Promise<{ q?: string }>
}) {
  return (
    <Suspense fallback={<>...</>}>
      <ClientSearch searchParams={searchParams} />
    </Suspense>
  )
}app/client-search.tsx
'use client'
 
import { use } from 'react'
 
export default function ClientSearch({
  searchParams,
}: {
  searchParams: Promise<{ q?: string }>
}) {
  const params = use(searchParams)
  return <div>Query: {params.q}</div>
}- 考虑将页面再次设为服务器组件,并将仅客户端代码(使用 useSearchParams)隔离到子客户端组件中。
app/search.tsx
'use client'
 
import { useSearchParams } from 'next/navigation'
import { Suspense } from 'react'
 
function Search() {
  const searchParams = useSearchParams()
 
  return <input placeholder="Search..." />
}
 
export function Searchbar() {
  return (
    // You could have a loading skeleton as the `fallback` too
    <Suspense>
      <Search />
    </Suspense>
  )
}禁用
注意:这仅适用于 Next.js 14.x 版本。如果您使用的是 14 以上的版本,请使用上述方法修复它。
我们不建议禁用此规则。但是,如果您需要,可以通过在 next.config.js 中将 missingSuspenseWithCSRBailout 选项设置为 false 来禁用它
next.config.js
module.exports = {
  experimental: {
    missingSuspenseWithCSRBailout: false,
  },
}此配置选项将在未来的主要版本中移除。
有用链接
这有帮助吗?