You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
  );
}

检查要点

  1. 确认ProductGrid是否需要客户端组件:若无交互需求,保持为服务端组件即可;若需交互,再添加"use client"。
  2. 验证Sanity Client配置:服务端组件中使用的Sanity Client不要暴露敏感信息(如token),避免安全风险。

内容的提问来源于stack exchange,提问作者aphex_triplet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 20:28:17