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

NextJS项目中无法通过ID从MongoDB删除数据

解决NextJS+MongoDB删除数据时的CastError问题

问题重现

使用NextJS开发项目时,调用findByIdAndDelete删除MongoDB数据时出现错误:

CastError: Cast to ObjectId failed for value "undefined" (type string) at path "_id" for model "Appointment"

错误原因

  1. 组件传参错误:在page.jsx中,你把整个appointment数组传给了DeleteAppointment组件,而非当前行的唯一标识_id,导致组件无法获取要删除的目标ID。
  2. 删除逻辑未正确获取ID:deleteAppointment.jsx里的handleDelete函数试图从参数解构id,但调用时未传入有效ID,最终传给API的id为undefined,mongoose无法将其转换为合法的ObjectId类型。

分步解决

1. 修正page.jsx的组件传参

在渲染DeleteAppointment时,传递当前行的_id和name(用于模态框提示):

// page.jsx 循环部分修改
<td className="flex">
  <UpdateAppointment appointmentId={row._id} />
  <DeleteAppointment appointmentId={row._id} appointmentName={row.name} />
</td>

2. 修正deleteAppointment.jsx的逻辑

接收传入的props,用正确ID发起请求,同时优化模态框提示:

"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";

// 接收组件传入的props
export default function DeleteAppointment({ appointmentId, appointmentName }) {
  const [modal, setModal] = useState(false);
  const router = useRouter();

  // 直接使用传入的appointmentId发起请求
  async function handleDelete() {
    await fetch(`http://localhost:3000/api/appointment?id=${appointmentId}`, {
      method: "DELETE",
    });
    router.refresh();
    setModal(false);
  }

  function handleChange() {
    setModal(!modal);
  }

  return (
    <div>
      <button className="btn btn-error btn-sm" onClick={handleChange}>
        Delete
      </button>

      <input
        type="checkbox"
        checked={modal}
        onChange={handleChange}
        className="modal-toggle"
      />

      <div className="modal">
        <div className="modal-box">
          {/* 显示要删除的用户名称 */}
          <h3 className="font-bold text-lg">
            Anda yakin untuk menghapus data "{appointmentName}"?
          </h3>

          <div className="modal-action">
            <button type="button" className="btn" onClick={handleChange}>
              Close
            </button>
            <button type="button" onClick={handleDelete} className="btn">
              Delete
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

3. 给API路由添加错误处理(可选但推荐)

避免无效ID导致服务端崩溃:

// API路由修改
import { connectMongoDB } from "@/lib/mongodb";
import Appointment from "@/models/appointment";
import { NextResponse } from "next/server";
import mongoose from "mongoose";

export async function DELETE(req) {
  const id = req.nextUrl.searchParams.get("id");
  
  // 校验ID合法性
  if (!id || !mongoose.Types.ObjectId.isValid(id)) {
    return NextResponse.json({ message: "无效的ID" }, { status: 400 });
  }

  await connectMongoDB();
  await Appointment.findByIdAndDelete(id);
  return NextResponse.json({ message: "Appointment deleted" }, { status: 200 });
}

关于id和_id的区别

  • _id:MongoDB自动为每个文档生成的主键,类型是ObjectId(MongoDB自定义的12字节标识符)。
  • id:我们在代码中通常用它指代_id的字符串形式,mongoose会自动将合法的字符串id转换为ObjectId类型执行数据库操作,但如果传入undefined或非法字符串,就会抛出你遇到的CastError。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:58:31