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

Next.js客户端组件使用async/await报错,求Prismadb分页解决方案

问题分析

错误原因很明确:标记了"use client"的客户端组件不能是async函数,也无法在组件渲染阶段直接使用await调用异步操作。你的StoreTable组件加了"use client"(因为要使用useProductPagination客户端状态钩子),但直接写成了async组件并awaitgetData,这违反了Next.js的客户端组件规则。

另外你的分页逻辑存在错误:prismadb.product.findMany里的skip和take参数写反了,正确的分页公式应该是:

  • take:每页显示的条数(对应你的perPage)
  • skip:跳过的条数,计算方式为(page - 1) * perPage
解决方案

下面提供两种可行的调整方案,你可以根据项目情况选择:

方案一:使用useEffect + useState在客户端组件中获取数据

保留客户端组件的状态管理,通过副作用钩子异步调用Server Action:

1. 修改客户端组件代码

"use client";
import { Products, columns } from "@/app/store/columns";
import { DataTable } from "@/app/store/data-table";
import { getData } from "@/lib/store/get-product";
import { useProductPagination } from "@/lib/store/product-pagination";
import React, { useState, useEffect } from "react";

function StoreTable() {
  const { page, perPage } = useProductPagination();
  const [data, setData] = useState<Products[]>([]);
  const [loading, setLoading] = useState(true);

  // 当page或perPage变化时,重新获取数据
  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      const result = await getData(perPage, page);
      setData(result);
      setLoading(false);
    };

    fetchData();
  }, [page, perPage]);

  if (loading) {
    return <div>加载中...</div>;
  }

  return (
    <div className="w-screen pr-4 sm:pr-8 md:pr-10 max-w-7xl mx-auto">
      <DataTable data={data} columns={columns} />
    </div>
  );
}

export default StoreTable;

2. 修正Server Action的分页逻辑

import { Products } from "@/app/store/columns";
import prismadb from "../prismadb";

export async function getData(perPage: number, page: number): Promise<Products[]> {
    const products = await prismadb.product.findMany({
      // 修正skip和take的逻辑
      skip: (page - 1) * perPage,
      take: perPage,
    });
  
    return products.map((product, i) => ({
      id: i + 1,
      name: product.name,
      description: product.description,
      category: product.category,
      origin: product.origin,
      sell: product.sellingPrice,
      purchase: product.purchasedPrice,
      amount: Math.random() * 100,
      status: product.status === "active" ? "active" : "inactive",
    }));
}

方案二:使用SWR简化数据获取(推荐)

如果你的项目已经使用SWR,或者想要更简洁的缓存和重逻辑,可以用SWR来处理异步数据获取:

1. 安装SWR(如果没装的话)

npm install swr
# 或
yarn add swr

2. 修改客户端组件

"use client";
import { Products, columns } from "@/app/store/columns";
import { DataTable } from "@/app/store/data-table";
import { getData } from "@/lib/store/get-product";
import { useProductPagination } from "@/lib/store/product-pagination";
import useSWR from "swr";

// 定义SWR的fetcher函数
const fetcher = async ([perPage, page]: [number, number]) => {
  return getData(perPage, page);
};

function StoreTable() {
  const { page, perPage } = useProductPagination();
  // 根据page和perPage作为key,自动触发数据获取
  const { data, isLoading } = useSWR([perPage, page], fetcher);

  if (isLoading || !data) {
    return <div>加载中...</div>;
  }

  return (
    <div className="w-screen pr-4 sm:pr-8 md:pr-10 max-w-7xl mx-auto">
      <DataTable data={data} columns={columns} />
    </div>
  );
}

export default StoreTable;

3. 同样修正Server Action的分页逻辑(同方案一的第二步)

关键注意点
  • 客户端组件不能是async函数,所有异步操作必须放到useEffect、SWR/React Query这类工具中处理
  • 分页逻辑一定要注意skip和take的正确计算,否则会出现数据重复或缺失的问题
  • Server Action本身是服务端运行的,不需要额外标记,确保它不在客户端组件的导入链中被强制客户端渲染(你的getData目前没问题,因为它没有"use client"标记)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:15:24