Next.js 14+Sanity报错排查:客户端组件不支持async/await
解决Next 14中异步组件在客户端组件调用的错误
问题核心
你遇到的async/await is not yet supported in Client Components, only Server Components错误,本质是Next.js App Router的组件规则限制:带"use client"的客户端组件不能直接渲染异步的服务端组件,而你的ProductGridApp是异步服务端组件,却被在加了"use client"的page.tsx中直接调用,同时你还存在组件内容硬编码的问题(导致页面显示异常)。
具体解决方案
方案1:将page.tsx改为服务端组件(推荐,无客户端交互需求时)
如果你的页面不需要客户端交互(比如不需要useState、useEffect等hooks),直接移除page.tsx顶部的"use client"指令:
- 移除后
page.tsx会自动成为服务端组件,可直接调用异步的ProductGridApp,不会触发错误。
方案2:当page.tsx必须是客户端组件时
如果页面需要客户端交互(比如购物车状态管理、UI交互),需用React.Suspense包裹异步服务端组件,处理加载状态:
修改page.tsx代码:
"use client"; import { Suspense } from "react"; import ProductGridApp from "./path-to/ProductGridApp"; // 替换为实际路径 export default function ShopPage() { return ( <Suspense fallback={<div>加载商品中...</div>}> <ProductGridApp /> </Suspense> ); }
同时确保ProductGridApp没有添加"use client"指令(保持为服务端组件,异步获取数据合法)。
额外修复:修正ProductGrid的硬编码问题
你的ProductGrid组件里显示的是固定文本Name和Price,这也是页面显示异常的原因之一,修改后才能正确渲染商品信息:
import Image from "next/image"; import Link from "next/link"; import { urlForImage } from "../../imgsandbox/sanity/lib/image"; import { XCircle } from "lucide-react"; import { formatCurrencyString } from "use-shopping-cart"; import { SanityProduct } from "../../imgsandbox/config/inventory"; interface Props { products: SanityProduct[]; } // 若需要客户端交互(如加购按钮),再添加"use client" // "use client"; export function ProductGrid({ products }: Props) { if (!products || products.length === 0) { return ( <div className="mx-auto grid h-40 w-full place-items-center rounded-md border-2 border-dashed bg-gray-50 py-10 text-center dark:bg-gray-900"> <div> <XCircle className="mx-auto h-10 w-10 text-gray-500 dark:text-gray-200" /> <h1 className="mt-2 text-xl font-bold tracking-tight text-gray-500 dark:text-gray-200 sm:text-2xl"> No products found </h1> </div> </div> ); } return ( <div className="grid grid-cols-1 gap-x-6 gap-y-10 sm:grid-cols-3 lg:col-span-3 lg:gap-x-8"> {products.map((product) => ( <Link key={product._id} href={`/products/${product.slug}`} className="group text-sm" > <div className="aspect-h-1 aspect-w-1 w-full overflow-hidden rounded-lg border-2 border-gray-200 bg-gray-100 group-hover:opacity-75 dark:border-gray-800"> <Image src={urlForImage(product.images[0])} alt={product.name} width={225} height={280} className="h-full w-full object-cover object-center" /> </div> <h3 className="mt-4 font-medium">{product.name}</h3> <p className="mt-2 font-medium"> {formatCurrencyString({ value: product.price, currency: product.currency })} </p> </Link> ))} </div> ); }
检查要点
- 确认
ProductGrid是否需要客户端组件:若无交互需求,保持为服务端组件即可;若需交互,再添加"use client"。 - 验证Sanity Client配置:服务端组件中使用的Sanity Client不要暴露敏感信息(如token),避免安全风险。
内容的提问来源于stack exchange,提问作者aphex_triplet
相关产品推荐
相关产品推荐

