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

Next.js 13服务端组件传数据至客户端组件警告问题排查

问题排查与修复方案

核心问题分析

你的代码存在四个关键错误,直接导致了警告和客户端无法正常获取数据的问题:


1. API路由不符合Next.js 13 App Router规范

Next.js 13的App Router中,API路由必须通过导出对应HTTP方法的函数(如GET)来处理请求,而非默认导出普通函数。你当前的默认导出函数不会被框架正确识别为API处理逻辑,导致响应格式异常。

2. NextResponse响应构造错误

你使用new NextResponse({dataJson})返回数据,这不会将对象正确序列化为标准JSON格式。客户端收到的不是可解析的JSON响应,自然无法提取有效数据。正确做法是使用NextResponse.json()方法返回JSON响应。

3. MongoDB ObjectId未转为纯字符串

product._id是MongoDB的ObjectId对象(即使调用了.lean()),属于非纯JavaScript对象。直接将其包含在返回对象中会触发「only plain objects can be passed from server components to client components」警告,同时导致客户端无法正确处理该字段。

4. 冗余的JSON序列化操作

JSON.parse(JSON.stringify(productDetails))属于无效操作,productDetails已经是纯对象结构,重复序列化再解析不仅没必要,还可能引入额外的数据格式问题。


修正后的代码

服务端API代码(app/api/product/[id]/route.js)

import db from "../../../../utils/db";
import Product from "../../../../models/Product";
import { NextResponse } from "next/server";

// 改为导出GET方法函数,符合App Router API规范
export async function GET(request, { params, searchParams }) {
  try {
    await db.connectDb();
    const id = params.id;
    const size = searchParams.size;
    const style = searchParams.style;
    
    // 使用lean()获取纯对象,手动处理ObjectId为字符串
    const product = await Product.findById(id).lean();
    if (!product) {
      return NextResponse.json({ error: "Product not found" }, { status: 404 });
    }

    const subProduct = product.subProducts[style];
    const sizeData = subProduct.sizes[size];
    const discount = subProduct.discount;
    const priceBefore = sizeData.price;
    const price = discount ? priceBefore - priceBefore / discount : priceBefore;

    // 确保所有字段都是纯对象/基础类型,显式转换ObjectId为字符串
    const productDetails = {
      _id: product._id.toString(), // 关键修正:转为字符串
      style: Number(style),
      name: product.name,
      description: product.description,
      slug: product.slug,
      sku: subProduct.sku,
      brand: product.brand,
      category: product.category,
      subCategories: product.subCategories,
      shipping: product.shipping,
      images: subProduct.images,
      color: subProduct.color,
      size: sizeData.size,
      price,
      priceBefore,
      quantity: sizeData.qty,
    };

    // 直接用NextResponse.json返回纯对象
    return NextResponse.json(productDetails);
  } catch (error) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  } finally {
    await db.disconnectDb();
  }
}

客户端组件代码(新增错误捕获,确保请求稳定性)

const addToCartHandler = async () => {
  if (!size) {
    setError("Please Select a size");
    return;
  }
  try {
    // 确认dsize变量与业务逻辑一致
    const { data } = await axios.get(
      `/api/product/${product._id}?style=${product.style}&size=${dsize}`
    );
    
    console.log("Received data:", data);
    if (qty > data.quantity) {
      setError(
        "The Quantity you have chosen is more than in stock. Try and lower the Qty"
      );
    } else if (data.quantity < 1) {
      setError("This Product is out of stock.");
      return;
    } else {
      let _uid = `${data._id}_${product.style}_${dsize}`;
      console.log("Generated UID:", _uid);
      let exist = cart.cartItems.find((p) => p._uid === _uid);
      if (exist) {
        let newCart = cart.cartItems.map((p) => {
          if (p._uid === exist._uid) {
            return { ...p, qty: qty };
          }
          return p;
        });
        dispatch(updateCart(newCart));
      } else {
        dispatch(
          addToCart({
            ...data,
            qty,
            size: data.size,
            _uid,
          })
        );
      }
    }
  } catch (error) {
    // 新增错误捕获,排查请求失败原因
    setError("Failed to fetch product details: " + error.message);
    console.error("Request error:", error);
  }
};

额外注意事项

  • 确认API路由文件路径正确:App Router下API路由需遵循app/api/[path]/route.js结构,比如app/api/product/[id]/route.js。
  • 检查dsize变量是否与业务逻辑中的size变量一致,避免参数传递错误。
  • 新增的错误捕获可以帮助快速定位请求过程中的异常(如API路由不存在、数据库连接失败等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:50:13