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

Next.js 13 App Router动态分段获取失败与MongoDB查询报错

问题:Next.js 13 App Router单条数据查询失败,全量查询正常

使用Next.js 13的App Router与API Router,MongoDB作为数据库管理系统。查询集合所有数据时成功,但查询单条数据时失败,报错如下:

TypeError: Cannot read properties of undefined (reading 'id')
    at GET (webpack-internal:///(sc_server)/./app/api/shop/[id]/route.tsx:14:30)
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:265:43)
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/lib/trace/tracer.js:111:36)
    at NoopContextManager.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:360:30)
    at ContextAPI.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:30:58)
    at NoopTracer.startActiveSpan (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:953:34)
    at ProxyTracer.startActiveSpan (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:993:36)
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/lib/trace/tracer.js:100:107)
    at NoopContextManager.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:360:30)
    at ContextAPI.with (webpack-internal:///(sc_server)/./node_modules/next/dist/compiled/@opentelemetry/api/index.js:30:58)
    at NextTracerImpl.trace (webpack-internal:///(sc_server)/./node_modules/next/dist/server/lib/trace/tracer.js:100:32)
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:253:53)
    at AsyncLocalStorage.run (node:async_hooks:330:14)
    at Object.wrap (webpack-internal:///(sc_server)/./node_modules/next/dist/server/async-storage/static-generation-async-storage-wrapper.js:41:24)
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:207:97)
    at AsyncLocalStorage.run (node:async_hooks:330:14)
    at Object.wrap (webpack-internal:///(sc_server)/./node_modules/next/dist/server/async-storage/request-async-storage-wrapper.js:77:24)
    at eval (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:206:75)
    at AsyncLocalStorage.run (node:async_hooks:330:14)
    at AppRouteRouteModule.execute (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:203:56)
    at AppRouteRouteModule.handle (webpack-internal:///(sc_server)/./node_modules/next/dist/server/future/route-modules/app-route/module.js:326:41)
    at RouteHandlerManager.handle (D:\Projects\MyShop\node_modules\next\dist\server\future\route-handler-managers\route-handler-manager.js:28:29)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async doRender (D:\Projects\MyShop\node_modules\next\dist\server\base-server.js:996:38)
    at async cacheEntry.responseCache.get.incrementalCache.incrementalCache (D:\Projects\MyShop\node_modules\next\dist\server\base-server.js:1172:40)
    at async D:\Projects\MyShop\node_modules\next\dist\server\response-cache\index.js:99:36

单条数据查询代码(路径:/app/api/shop/[id]/route.tsx)

import { connectToDatabase } from "@/lib/mongo";
import { NextRequest, NextResponse } from "next/server";
import { ObjectId } from "mongodb";

export async function GET (req : NextRequest, res : NextResponse) {
  try {
    const id = req.query.id;
    const client = await connectToDatabase();
    const db = client.db("MyShopDB");
    // console.log(req);
  
    const oneProduct = await db.collection("Products").findOne({ _id: ObjectId(id) });
  
    // return new Response(JSON.stringify(allProducts), { status: 200 });
    if(oneProduct)
      return NextResponse.json(oneProduct)
    else 
      return res.status(404).json({message: "Products Not Found"})
  } catch (error) {
    console.log(error);
    return new Response("Failed to fetch all prompts", { status: 500 })
  }
}

全量数据查询代码(路径:/app/api/shop/route.tsx)

import { connectToDatabase } from "@/lib/mongo";
import { NextRequest, NextResponse } from "next/server";

export async function GET (req: NextRequest, res: NextResponse) {
  try {
    const client = await connectToDatabase();
    const db = client.db("MyShopDB");
    console.log(req);
  
    const allProducts = await db.collection("Products").find().toArray();
  
    // return new Response(JSON.stringify(allProducts), { status: 200 });
    return NextResponse.json(allProducts);
  } catch (error) {
    return new Response("Failed to fetch all prompts", { status: 500 })
  }
}

解决方案

问题根源

  1. 动态路由参数获取错误:Next.js 13 App Router的API路由中,动态路由参数(如[id])并非从req.query获取,而是通过函数的第二个参数params对象获取。原代码错误地将第二个参数定义为res: NextResponse,导致无法拿到路由参数。
  2. Response对象使用错误:原代码在else分支中使用res.status(404),但res并非有效的Response对象,应该统一使用NextResponse构建响应。

修正后的代码

import { connectToDatabase } from "@/lib/mongo";
import { NextRequest, NextResponse } from "next/server";
import { ObjectId } from "mongodb";

export async function GET(req: NextRequest, { params }: { params: { id: string } }) {
  try {
    const { id } = params;
    const client = await connectToDatabase();
    const db = client.db("MyShopDB");

    const oneProduct = await db.collection("Products").findOne({ _id: new ObjectId(id) });

    if (oneProduct) {
      return NextResponse.json(oneProduct);
    } else {
      return NextResponse.json({ message: "产品未找到" }, { status: 404 });
    }
  } catch (error) {
    console.error(error);
    return NextResponse.json({ message: "获取产品失败" }, { status: 500 });
  }
}

关键修正点

  • 调整GET函数的第二个参数,改为接收包含路由参数的params对象,从中提取id
  • 移除错误的res参数,统一使用NextResponse生成响应
  • 实例化ObjectId时添加new关键字(部分版本允许省略,但更规范)
  • 优化错误提示文本为中文(可根据需求调整)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:09:58