skip to Main Content

I’m making an app in nextjs to practice, and I am having a hard time getting single data to delete from the database using the findByIdAndDelete function.

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

./page.jsx


import AddAppointment from "./addAppointment";
import DeleteAppointment from "./deleteAppointment";
import UpdateAppointment from "./updateAppointment";

async function getAppointment() {
  const res = await fetch("http://localhost:3000/api/appointment", {
    method: "GET",
    cache: "no-store",
  });
  // const data = await res.json();
  return res.json();
}

async function Appointment() {
  const { appointment } = await getAppointment();

  return (

    <div className="py-10 px-10">
      <div className="py-2">
        <AddAppointment />
      </div>
      <table className="table w-full">
        <thead>
          <tr>
            <th>#</th>
            <th>Nama</th>
            <th>Tanggal</th>
            <th>No Telp.</th>
            <th>Terapis</th>
            <th>Status</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>
          {appointment.map((row, i) => (
            <tr key={row._id}>
              <td>{i + 1}</td>
              <td>{row.name}</td>
              <td>{row.date}</td>
              <td>{row.phone}</td>
              <td>{row.terapist}</td>
              <td>{row.statust || "unknown"}</td>
              <td className="flex">
                <UpdateAppointment {...appointment} />
                <DeleteAppointment {...appointment} />
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export default Appointment;

./deleteAppointment.jsx

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

export default function DeleteAppointment() {
  const [modal, setModal] = useState(false);

  const router = useRouter();

  async function handleDelete({ id }) {
    await fetch(`http://localhost:3000/api/appointment?id=${id}`, {
      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 ""?
          </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>
  );
}

api route

import { connectMongoDB } from "@/lib/mongodb";
import Appointment from "@/models/appointment";
import { NextResponse } from "next/server";

export async function DELETE(req) {

  const id = req.nextUrl.searchParams.get("id");
  await connectMongoDB();
  await Appointment.findByIdAndDelete(id);
  return NextResponse.json({ message: "Appointment deleted" }, { status: 200 });
}

Model

import mongoose, { Schema, models } from "mongoose";

const appointmentSchema = new Schema(
  {
    name: {
      type: String,
      required: true,
    },
    date: {
      type: String,
      required: true,
    },
    phone: {
      type: String,
      required: true,
    },
    terapist: {
      type: String,
      required: true,
    },
    statust: {
      type: String,
      required: true,
    },
  },
  { timestamps: true }
);

const Appointment =
  models.Appointment || mongoose.model("Appointment", appointmentSchema);
export default Appointment;

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

having hard time to figure how to passing id and difference between id and _id

2

Answers


  1. It seems that the error is not within your db orm but at where you are passing the ID, can you check what is the value in id the error states that the id that you are passing is undefined. Please check the value and ensure that it is being passed correctly.

    Login or Signup to reply.
  2. There’s no parameter sent with the onClick function. So, the id parameter is undefined. Therefore, it sends an API request with an undefined id parameter like this: http://localhost:3000/api/appointment?id=undefined

    On the client side, it is necessary to use an ObjectID to delete a document by using findByIdAndDelete() but the ID parameter comes from the request as undefined, not an ObjectID. Therefore, it can’t find the related document from DB and returns this error.

    As a result, the issue is related to the client side. Need to send the correct ID to be deleted with the API parameter. Therefore, need to get the related row or only the id value as props in the DeleteAppointment component.

    It would be better to send the whole row object into props if you will need to use other fields as well:

    // Send related row as prop 
    <DeleteAppointment row={row} />
    

    Otherwise, it’s enough to send only id:

    // Send only the related row's ID field as a prop
    <DeleteAppointment id={row.id} />
    

    Then get the props as a parameter in the DeleteAppointment component:

    export default function DeleteAppointment(props) {
    ...
    }
    

    After that, because of reaching the related id into the props, you can use props.id or props.row.id in the request id instead of the id parameter:

    async function handleDelete() {
      await fetch(`http://localhost:3000/api/appointment?id=${props.id}`, {
          method: "DELETE",
      });
    
      router.refresh();
      setModal(false);
    }
    

    If you send the whole row object as a prop, then you can use props.row.id:

    async function handleDelete() {
      await fetch(`http://localhost:3000/api/appointment?id=${props.row.id}`, {
          method: "DELETE",
      });
    
      router.refresh();
      setModal(false);
    }
    

    Hope, it’s clear and helpful

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search